三、内存分配

1. JVM 简化架构概览

在这里插入图片描述

1.1 运行时数据区(即内存区域,又称 JVM 内存结构)

如上面的 JVM 简化架构图所示,内存区域分为如下五个部分(这五个部分统称为运行时数据区):

  1. PC 寄存器(又称程序计数器);

  2. Java 栈(又称 Java 虚拟机栈,或虚拟机栈);

  3. Java 堆;

  4. 方法区;

    注意:运行时常量池是划分在方法区中的。

  5. 本地方法栈(Native 栈)

1.1.1 PC 寄存器(又称程序计数器)

PCProgram Counter)寄存器说明:

  1. PC 寄存器是线程私有的,即每个线程拥有一个 PC 寄存器,用来存储指向下一条指令的地址。

    PC 寄存器中指令的存储顺序就是线程中代码的执行顺序。

  2. 在创建线程的时候,创建相应的 PC 寄存器。

  3. 执行本地方法(即 native 修饰的 jni 方法)时,PC 寄存器的值为 undefined

  4. PC 寄存器是一块较小的内存空间,是唯一一个在 JVM 规范中没有规定 OutOfMemoryError 的内存区域。

1.1.2 Java 栈(又称 Java 虚拟机栈,或虚拟机栈)

Java 栈的说明:

  1. Java 栈是由一系列的帧(Frame)组成的。因此,Java 栈也称为帧栈。

    Java 栈和 PC 寄存器一样,都是线程私有的。

    由帧组成的栈叫做帧栈;

    存放在帧栈中的帧叫做栈帧。

  2. 帧(即 栈帧)可以用来保存一个方法的局部变量、操作数栈(Java 没有寄存器,所有参数传递使用操作数栈)、常量池指针、动态链接、方法返回值等。

  3. 每一次方法调用时都会创建一个帧,并压栈。退出方法时,修改栈顶指针就可以把栈帧中的内容销毁。

    帧是方法调用相关的。方法调用开始时创建帧,方法调用结束后销毁帧。

  4. 局部变量表 存放了编译期可知的各种基本数据类型和引用类型,每个 slot(槽位) 存放 32 位的数据,longdouble 占两个 slot

    局部变量表中的槽位(slot)是可以复用的。

    参考 Code 属性在 class 文件中的解析举例。

    参考 《字节码执行引擎》 中的 局部变量表

Java 栈的优缺点:

  1. 优点:存取速度比堆快,仅次于寄存器。

  2. 缺点:存在栈中的数据大小、生存期是在编译期决定的,缺乏灵活性。

1.1.3 Java

Java 堆说明:

  1. 用来存放应用系统创建的对象和数组。所有线程共享 Java 堆。

  2. GC 主要就是管理堆空间。对分代 GC 来说,堆也是分代的。

    分代只是一种思想,内存中并没有分代的说法。

Java 堆的优缺点:

  1. 优点:运行期动态分配内存大小;自动进行垃圾回收。

  2. 缺点:效率相对较慢。

1.1.4 方法区

方法区的说明:

  1. 方法区是线程共享的,通常用来保存加载的类的结构信息(即 class 文件中的二进制字节流数据,包括:类名、继承关系、字段、方法、附加属性等信息数据)。

    参考 类加载要完成的功能。

    参考 Class 文件的格式。

  2. 方法区通常和元空间(Meta Space)关联在一起。但具体的跟 JVM 实现和 JDK 版本有关。

    JDK 8 之前,方法区和永久区关联在一起;

    JDK 8 之后,废除了永久区,将方法区和元空间关联在一起。

  3. JVM 规范把方法区描述为堆的一个逻辑部分,但方法区有一个别名(即 Non-heap 非堆),应该是为了与 Java 堆相互区分开来。

1.1.5 运行时常量池

运行时常量池是 class 文件中每个类或接口的 常量池表,在运行期间的表示形式,通常包括:JDK 版本、类名、父类或父接口名、字段、方法等信息。

运行时常量池分配在方法区中。

因此,说方法区中保存了类的结构信息是正确的。

通常在加载类和接口到 JVM 后,就创建了相应的运行时常量池。

1.1.6 本地方法栈(Native 栈)

JVM 中用来支持 native 方法执行的栈就是本地方法栈。

1.2 Java 栈、Java 堆、方法区三者间的交互关系

在这里插入图片描述

如上图所示:

  1. 对于 Java 栈中的局部变量表中的类类型的局部变量,会指向 Java 堆中的类对象;

  2. 对于 Java 堆中的类对象,它不仅包括实例数据,还包括指向该类元数据信息的指针;

  3. 对于类的元数据信息,就是方法区中保存的类的结构信息等,即 Java 堆中的类对象还会持有对方法区中数据的引用。

2. Java

2.1 堆内存概述

Java 堆用来存放应用系统创建的对象和数组,所有线程共享 Java 堆。

在运行时期为 Java 堆动态分配内存大小,并自动进行垃圾回收。

Java 垃圾回收(GC)主要就是回收堆内存。

对分代 GC 来说,堆也是分代的。

堆内存在逻辑上是连续的,在物理上可以是不连续的。

2.2 堆内存的结构

在这里插入图片描述

如上图所示:整个堆大小 = 新生代 + 老年代

2.2.1 新生代(Young Generation

新生代 = Eden + 存活区

新生代用来存放新分配的对象。

新生代中经过垃圾回收后,没有回收掉的对象被复制到老年代。

2.2.1.1 Eden(伊甸园)区
2.2.1.2 存活区(From SpaceTo Space

存活区(Survivor Space)又分为 From SpaceTo Space

但使用时,只能使用其中一个。

之所以分为两个,是为了在复制时用到。

2.2.2 老年代(Old Generation,又称年老代)

老年代中只有一个 Tenured Space(年老区)。

老年大存储的对象比新生代存储的对象的年龄大得多。

老年代存储一些大对象。

对一些占用空间较大的对象,可能不会先进入新生代,而是直接存放在老年代。

2.2.3 永久代(又称持久代,已废弃)& 元空间

从前的持久代(即用来存放 ClassMethod 等元信息的区域)从 JDK 8 开始去掉了。被元空间(MetaSpace)所取代。

元空间并不在虚拟机里面,而是直接使用本地内存。

2.3 对象的内存布局(对象头、实例数据、对齐填充)

HotSpot 虚拟机为例,对象在内存中的存储布局,分为:

  1. 对象头

    对象头包含两个部分:
    1. Mark Word:存储对象自身的运行数据,如:HashCode、GC 分代年龄、锁状态标志等。
    2. 类型指针:对象指向它的类的元数据(即类的结构信息)的指针(指向方法区)。
    
  2. 实例数据

    真正存放对象实例数据的地方。
    
  3. 对齐填充

    这部分不一定存在。也没有特别的含义,仅仅是占位符。
    因为 HotSpot 虚拟机要求对象起始地址都是 8 字节的整数倍,如果不是,就要对齐填充。
    

2.4 对象的访问方式(使用句柄、使用指针)

JVM 规范中,只规定了 reference 类型(引用类型)是一个指向对象的引用,但没有规定这个引用具体如何去定位,并访问堆中对象的具体位置。

因此,对象的访问方式取决于 JVM 的实现。目前主流的访问方式有:

  1. 使用句柄:

    Java 堆中会划分出一块内存来做为句柄池,reference 中保存句柄的地址。
    即引用指向句柄池中的句柄。
    句柄中存储对象的实例数据,以及类的元数据的地址。
    

    在这里插入图片描述

    使用句柄的优缺点:

    1. 优点:当对象发生改变时,只需要修改句柄中到对象数据的指针即可。不需要修改 reference 的指向。’

    2. 缺点:使用句柄其实就是采用间接引用的方式访问对象,于是,reference 需要 2 次寻址才能访问到对象。即访问速度较慢。

  2. 使用指针(HotSpot 虚拟机采用这种方式来访问对象):

    Java 堆中会存放访问类的元数据的地址,
    reference 存储的就直接是对象的地址。
    

    在这里插入图片描述

    使用指针的优缺点:

    1. 优点:reference 直接指向对象,只需 1 次寻址。即访问速度较快。

    2. 缺点:对象发生改变时,需要修改 reference 的指向。

3. Java 内存分配相关的参数设置

3.1 Trace 跟踪参数

3.1.1 -Xlog:gc(打印 GC 日志的简要信息)
3.1.2 -Xlog:gc*(打印 GC 日志的详细信息)
3.1.3 -Xlog:gc:<filename>(输出 GC 日志信息到指定文件)
如 -Xlog:gc:garbage-collection.log,其中 garbage-collection.log 是保存 GC 日志的文件。文件名前面还可以加路径,路径目录必须事先创建好。
3.1.4 -Xlog:gc+heap=debug(打印 GC 日志信息和堆信息)
3.1.5 GC 日志信息的格式

不同垃圾收集器的 GC 日志格式可能不同。GC 日志信息中主要包含以下内容:

  1. GC 发生的时间,也就是 JVM 从启动以来经过的秒数。

  2. 日志级别信息,和日志类型标记。

  3. GC 识别号。

  4. GC 类型,和 GC 的原因说明。

  5. 容量:GC 前容量 -> GC 后容量(该区域总容量)。

  6. GC 持续时间,单位:秒。

    有的收集器会有更详细的描述,比如:
    1. user:表示应用程序消耗的时间;
    2. sys:表示系统内核消耗的时间;
    3. real:表示操作从开始到结束的时间。
    

举例如下:

在这里插入图片描述

3.2 Java 堆的参数

3.2.1 -Xms<size>(初始堆大小)
设置堆的最小空间大小为 size,同时也将堆的初始空间大小设置为 size。size 必须是 1024 的倍数,且 size 必须大于 1MB。如:-Xms6291456-Xms6144k-Xms6m以上三种方式只是 size 的单位不同,结果都是将 size 设置为 6m。默认为物理内存的 1/64。如果不想将堆的最小空间大小和初始空间大小设置成一样,可以使用:
1. -XX:MinHeadpSize 单独设置最小空间大小;
2. -XX:InitialHeapSize 单独设置初始空间大小。
3.2.2 -Xmx<size>(最大堆大小)
默认为物理内存的 `1/4`。-Xmx 等价于 -XX:MaxHeapSize建议将 -Xms 和 -Xmx 设置成一样大小,即:初始堆大小 = 最大堆大小。这样,每次 GC 后就不需要再去调整堆大小了。

使用示例如下:

在这里插入图片描述

3.2.3 -Xmn<size>(新生代大小)
默认为整个堆的 3/8。因为新创建的对象一般都是存放在新生代中的,所以:
1. 如果新生代的内存太小,能够存放的对象就少,就会导致频繁的 GC;
2. 如果新生代的内存太大,就会存放过多的对象,从而导致一次 GC 的耗时较长。-Xmn 同时设置了新生代的初始空间大小和最大空间大小。也可以使用 -XX:NewSize 和 -XX:MaxNewSize 分别单独设置。
3.2.4 -XX:NewRatio(老年代与新生代的比例)
-XX:NewRatio 是设置新生代和老年代的占比关系。而 -Xmn 是设置新生代的固定内存大小。也就是说,对于 -XX:NewRatio, 新生代的内存大小取多少,是虚拟机根据比例来算的。默认值为 -XX:NewRatio=2,表示 老年代 : 新生代 = 2 : 1,即老年代占堆内存的 2/3新生代占堆内存的 1/3注意:如果 -Xms = -Xmx,且设置了 -Xmn,那么不用再设置 -XX:NewRatio。
3.2.5 -XX:SurvivorRatioEden 区和 Survivor 区的比例)
当 -XX:SurvivorRatio = 8 时,则 eden : from : to = 8 : 1 : 1,即:eden 区占新生代内存的 8/10;from space 占新生代内存的 1/10;to space 占新生代内存的 1/10。
3.2.6 -XX:+HeapDumpOnOutOfMemoryError(导出 OOM 时的堆信息)
导出 OOM 时的堆信息就是导出一个堆存储文件(hprof)文件。如果不通过参数 -XX:+HeapDumpPath 指定导出的 hprof 文件的路径,
则默认在程序运行时所在的当前目录下生成 hrof 文件。
3.2.7 -XX:+HeapDumpPathOOM 时堆信息的导出文件路径)
如果不指定导出路径,默认为 `Java` 程序运行时所在的当前目录。
3.2.8 -XX:OnOutOfMemoryError(在 OOM 时,执行一个脚本)
3.2.9 示例:GC 前后对象在堆内存中的分布变化

在这里插入图片描述

3.2.10 示例:分配的新生代内存不能超过最大堆内存的一半

-Xmn 设置的新生代内存超过了 -Xmx 设置的最大堆内存的一半时,实际给新生代分配的内存可能比 -Xmn 设置的小。

在这里插入图片描述

3.2.11 示例:导出堆存储文件并使用 MAT 进行内存分析

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3.2.12 示例:输出 GC 日志到指定文件

在这里插入图片描述

3.2.13 示例:-XX:NewRatio 设置老年代与新生代的比例

在这里插入图片描述

3.2.14 示例:-XX:SurvivorRatio 设置 Eden 区和 Survivor 区的比例

在这里插入图片描述

3.2.15 示例:分析内存溢出(OOM)时 GC 日志信息

在这里插入图片描述

3.3 Java 栈的参数

3.3.1 -Xss(栈的大小)
通常只有几百 K,决定了函数调用的深度。栈是由帧组成的,函数调用开始时创建帧,函数调用结束后销毁帧。
当函数嵌套调用时,就会同时有多个帧存在,嵌套层级越深,帧越多,
因此说 -Xss 所设置的栈大小,决定了一个栈中能同时存放下多少个帧,即确定了函数调用的嵌套深度。
3.3.2 示例:通过递归函数模拟 StackOverflowError(栈溢出异常)

在这里插入图片描述

3.4 元空间的参数

3.4.1 -XX:MetaspaceSize(初始空间大小)
3.4.2 -XX:MaxMetaspaceSize(最大空间大小)
默认是没有限制的
3.4.3 -XX:MaxMetaspaceFreeRatioGC 后的最大剩余百分比)
在 GC 之后,最小的 Metaspace 剩余空间容量的百分比。
3.4.4 -XX:MinMetaspaceFreeRatioGC 后的最小剩余百分比)
在 GC 之后,最大的 Metaspace 剩余空间容量的百分比。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/640031.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python-setup进阶打包命令

一、setup.py文件的书写 这个资料有很多&#xff0c;不多赘述&#xff0c;setup 函数常用的参数如下&#xff1a; 基础描述信息&#xff1a; name 包名称&#xff08;起一个响亮的名字&#xff09;version (-V) 包版本author 程序的作者author_email 程序的作者的邮箱地址mai…

Kafka-服务端-DelayedOperationPurgatory

DelayedOperationPurgatory是一个相对独立的组件&#xff0c;它的主要功能是管理延迟操作。 DelayedOperationPurgatory的底层依赖于Kafka提供的时间轮实现。 我们可以使用JDK本身提供的java.util.Timer或是DelayQueue轻松实现定时任务的功能&#xff0c;为什么Kafka还要专门…

图像处理之《用于统一源跟踪和深度伪造检测的深度可分离水印SepMark》论文精读

一、文章摘要 恶意的Deepfakes导致了一场关于区分真脸和伪造脸的激烈冲突。尽管已经制定了许多事后检测Deepfakes的对策&#xff0c;但毫无疑问&#xff0c;在可预见的操作之前&#xff0c;被动取证没有考虑对原始人脸采取任何预防措施。为了完成这个取证生态系统&#xff0c;…

月薪2W的软件测试工程师,到底是做什么的?

在生活中&#xff0c;我们常常会遇到以下几种窘迫时刻&#xff1a; 准备骑共享单车出行&#xff0c;却发现扫码开锁半天&#xff0c;车子都没有反应&#xff1b;手机导航打车&#xff0c;却发现地图定位偏差很大&#xff0c;司机总是跑错地方&#xff1b;买个水&#xff0c;却…

Redis实战之-分布式锁-redission

一、分布式锁-redission功能介绍 基于setnx实现的分布式锁存在下面的问题&#xff1a; 重入问题&#xff1a;重入问题是指 获得锁的线程可以再次进入到相同的锁的代码块中&#xff0c;可重入锁的意义在于防止死锁&#xff0c;比如HashTable这样的代码中&#xff0c;他的方法都…

​第14节-高质量简历写作求职通关-在线测试

在线测试主要包括性格测试、综合能力测试、技能测试三类 性格测试 性格测试主要用于考察个人与工岗位的匹配程度 考察内容包含性格、能力、动机、价值观等&#xff0c;考察形式一般为给出相应的工作场景&#xff0c;让你选择最喜欢或者最不喜欢的答案 技能考试 这类测试一般是针…

SpringMVC第一天

简介 SpringMVC技术与Servlet技术功能等同&#xff0c;均属于web层开发技术 SpringMVC是一种基于java实现的MVC模型的轻量级Web框架 优点 使用简单,开发便捷(相比于Servlet) 灵活性强 入门案例 第一步、导入SpringMVC与Servlet坐标 <?xml version"1.0" encod…

(Bean工厂的后处理器入门)学习Spring的第七天

一 . Bean工厂的后处理器入门 : 直接上图 BeanDefinitionRegistyPostProcessor 为 BeanFactoryProcessor的子接口 , 前者先执行(图里只有Bean工厂的后处理器第一个类型) 如下图 : 这两个接口可改变两个Map(BeanDefinitionMap , singletonObject)里的信息 (黑马只讲了BeanFact…

打造更智能的应用 - 机器学习和Andorid

打造更智能的应用 - 机器学习和Andorid 一、关于机器学习和Andorid二、使用 Gemini 让您的 Android 应用如虎添翼2.1 Gemini API2.2 Android AICore 三、现成可用的还是自定义的机器学习3.1 机器学习套件 SDK 的常见用户流3.2 高性能自定义机器学习 四、机器学习套件 SDK&#…

透明拼接屏生产商:如何选择合格供应商

随着透明拼接屏市场的不断扩大&#xff0c;越来越多的生产商加入其中。对于需求方而言&#xff0c;选择一家合格的生产商至关重要。本文将围绕如何选择透明拼接屏生产商展开讨论&#xff0c;同时结合对尼伽OLED显示屏的了解&#xff0c;为您推荐这一领域的优质供应商。 一、透明…

鸿蒙开发笔记(二十二): 页面路由(router),组件导航 Navigation, Tabs

1. 页面路由 router 页面路由指在应用程序中实现不同页面之间的跳转和数据传递。HarmonyOS提供了Router模块&#xff0c;通过不同的url地址&#xff0c;可以方便地进行页面路由&#xff0c;轻松地访问不同的页面。本文将从页面跳转、页面返回和页面返回前增加一个询问框几个方…

和平精英如何针对伏地魔

我的办法是开启颜色反转 一般安卓手机有这种功能 比如我是橘子系统4.0 橘子系统永远得神。 开启颜色反转 进入设置–快捷与辅助/更多设置–无障碍/辅助功能–颜色反转–打开开关即可。 注&#xff1a;颜色反转即增强显示内容的对比度&#xff0c;使对低对比度内容识别力差的人…

基于Pytorch做深度学习,但是代码水平很低,应该如何学习呢?

PyTorch是一个Python程序库&#xff0c;有助于构建深度学习项目。它强调灵活性&#xff0c;并允许用深度学习领域惯用的Python来表示深度学习模型。它的易用性使得它在研究社区中有了早期的使用者&#xff0c;并且在第1次发布之后的几年里&#xff0c;它已经成为应用程序中使用…

机器学习实验报告——EM算法

目录 一、算法介绍 1.1算法背景 1.2算法引入 1.3算法假设 1.4算法原理 1.5算法步骤 二、算法公式推导 2.1数学基础 2.2EM算法推导 三、算法实现 3.1关于EM聚类 3.2EM工具包的使用 3.3 实例测试 四、算法讨论 4.1EM算法的优缺点 4.2EM算法的应用 4.3对于EM算法…

信息安全概述

信息安全&#xff1a;防止任何对数据进行未授权访问的措施&#xff0c;或者防止造成信息有意无意泄漏、破坏、丢失等问题的发生&#xff0c;让数据处于远离危险、免于威胁的状态或特性。 网络安全&#xff1a;计算机网络环境下的信息安全。 信息安全现状及挑战 数字化时代威…

7.12、中间人攻击(ARP欺骗)

一、ARP协议原理 地址解析协议(Address Resolution Protocol&#xff0c;ARP)&#xff0c;负责把目的主机的IP 地址解析成目的MAC地址&#xff0c;地址解析的目标就是发现逻辑地址与物理地址的映射关系。网络中的计算机、交换机、路由器等都会定期维护自己的ARP缓存表。 为什么…

第6章 SpringBoot缓存管理

学习目标 了解SpringBoot的默认缓存 熟悉SpringBoot中Redis的缓存机制及实现 掌握SpringBoot整合Redis的缓存实现 缓存是分布式系统中的重要组件&#xff0c;主要解决数据库数据的高并发访问问题。在实际开发中&#xff0c;尤其是用户访问量较大的网站&#xff0c;为了提高服…

HarmonyOS SDK,助力开发者打造焕然一新的鸿蒙原生应用

鸿蒙生态千帆启航仪式于1月18日正式启动。从2019年HarmonyOS正式发布到2020年“没有人能够熄灭漫天星光”&#xff0c;今天&#xff0c;满天星光终汇成璀璨星河&#xff0c;HarmonyOS NEXT鸿蒙星河版重磅发布&#xff0c;带来了全新架构、全新体验、全新生态。作为支撑鸿蒙原生…

Spring--@Async解析

一、Async 简介 从Spring3开始提供了Async注解&#xff0c;被该注解标注的方法&#xff0c;Spring底层会新建一个线程池或者使用已有的线程池中的线程去异步的执行被标注的方法。 二、Async 工作原理 Async与Transactional 工作原理基本是一样的&#xff0c;也是通过Spring …

100天精通鸿蒙从入门到跳槽——第11天:TypeScript 知识储备:装饰器

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通Golang》…