深入浅出JVM(Ⅱ):Java内存区域
2021-03-27 15:25
标签:msi 本地 ima 工作 特殊 版本 https 现在 如何 字节码解释器工作时就是通过改变计数器的值来选择下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖计数器完成。 如果线程在执行java方法,计数器记录的是正在执行的虚拟机字节码指令地址。如果执行的是Native方法,计数器值为空。 此内存区域是唯一一个在Java虚拟器规范中没有规定任何OutOfMemoryError情况的区域。 栈帧用于储存局部变量表、操作数栈、常量池指针、动态链接、方法返回值等信息。每个方法的调用到完成对应着栈帧在虚拟机栈中的入栈到出栈。 每一次方法调用创建一个帧,并压栈,退出方法时,修改栈顶指针就可以把栈帧中的内容销毁。 局部变量表存放了编译期可知的各种基本数据类型和引用数据类型,每个slot(插槽)存放32位的数据,long、double占两个槽位。 栈的优点:存取速度比堆快,仅次于寄存器 栈的缺点:存在栈中的数据大小、生存期是在编译器决定的,缺乏灵活性 此区域可能出现的两种异常: 作用与虚拟机栈相似,区别是虚拟机栈为虚拟机执行的Java方法(也就是字节码)服务,而本地方法栈为虚拟机使用的Native方法服务。 与虚拟机栈一样,本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异常 垃圾收集器管理的主要区域,从垃圾回收角度看,由于现在收集器基本采用分代回收算法,Java堆可细分为: 堆的优点:运行期动态分配内存大小,自动进行垃圾回收 堆的缺点:效率相对较慢 可利用参数 此区域可能出现的异常: 可利用参数 此区域可能出现的异常: 在 JDK1.8 中已经移除了方法区(永久代),并使用了一个元数据区域进行代替(Metaspace)。 默认情况下元数据区域会根据使用情况动态调整,避免了在 1.7 中由于加载类过多从而出现 java.lang.OutOfMemoryError: PermGen。 但也不能无线扩展,因此可以使用 运行时常量池是方法区的一部分。是Class文件中每个类或接口的常量池表,在运行期间的表示形式,通常包括:类的版本、字段、方法、接口等信息 直接内存不是虚拟机运行时数据区的一部分。它是通过在堆内存中的 既然是内存,那也得是可以被回收的。但由于堆外内存不直接受 JVM 管理,所以常规 GC 操作并不能回收堆外内存。它是借助于老年代产生的 fullGC 顺便进行回收。同时也可以显式调用 System.gc() 方法进行回收(前提是没有使用 -XX:+DisableExplicitGC 参数来禁止该方法)。 值得注意的是:由于堆外内存也是内存,是由操作系统管理。如果应用有使用堆外内存则需要平衡虚拟机的堆内存和堆外内存的使用占比。避免出现堆外内存溢出。 (以下探讨的对象限于java对象,不包含数组和Class对象) 在HotSpot虚拟机中,对象在内存中的存储布局可以分为3块区域:对象头(Header)、实例数据(Instance Data)、对齐填充(Padding) 对象头包含两部分: 存放对象实力数据 不一定存在,占位符,没有特殊含义,HotSpot要求对象起始地址必须是8的整数倍,对象实例部分没有对齐时需要通过对齐填充补齐。 对象的访问定位取决于具体的虚拟机实现。创建对象实例后,需要通过虚拟机栈中的reference类型数据来操作堆上的对象。现在主流的访问方式有使用句柄和直接指针两种: Java堆会划分一块内存作为句柄池,reference中存的是对象的句柄地址,句柄中包含对象实例数据和类型数据各自的具体地址信息。 优势:reference中存储的是稳定的句柄指针,对象被移动时只会改变句柄中的实力数据指针,而reference本身不需要修改。 优势:速度更快,节省了一次指针定位开销。 深入浅出JVM(Ⅱ):Java内存区域 标签:msi 本地 ima 工作 特殊 版本 https 现在 如何 原文地址:https://www.cnblogs.com/haif/p/13657734.html运行时数据区
程序计数器/PC寄存器
线程私有
,程序计数器是一块较小的内存空间,当前线程所执行的字节码的行号指示器。Java虚拟机栈
线程私有
,生命周期与线程相同。描述的是Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧。
本地方法栈
Java堆
线程共享区域
,是整个虚拟机内存中最大的一块。在虚拟机启动时创建,用于存放对象实例。新生代
和老年代
;再细致有Eden
空间、From Survivor
空间、To Survivor
空间等。-Xms
-Xmx
进行堆内存控制。
方法区(JDK1.7)
线程共享区域
,方法区主要用于存放已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码。 这块区域也被称为永久代。-XX:PermSize
-XX:MaxPermSize
控制初始化方法区和最大方法区大小。
元数据区(JDK1.8)
-XX:MaxMetaspaceSize
来控制最大内存。运行时常量池
直接内存
DirectByteBuffer
对象操作的堆外内存,避免了堆内存
和堆外内存
来回复制交换复制。对象的创建、内存布局、访问定位
对象的创建
对象的内存布局
对象头
(如果对象是Java数组,对象头中还必须有一块用于记录数组长度的数据,因为虚拟机可以通过普通Java对象的元数据信息确定Java对象的大小,但是从数组元数据中无法确认数组大小)实例数据
对齐填充
对象的访问定位
使用句柄访问
使用直接内存访问
下一篇:javascript
文章标题:深入浅出JVM(Ⅱ):Java内存区域
文章链接:http://soscw.com/index.php/essay/68627.html