JVM
分类:
文章
•
2024-12-05 16:40:46
Java内存区域与内存溢出异常
运行时数据区域
-
概览
-
程序计数器
如果线程正在执行的是一个java方法,那么PC对应的是虚拟机字节码指令的地址; 如果正在执行的是本地(Native)方法,PC值为空
-
虚拟机栈
虚拟机栈中放置栈帧,一个栈帧对应一个方法调用!栈帧存放以下内容:局部变量表、操作数栈、动态链接、返回地址等
-
本地方法栈
与虚拟机栈类似,不过存放的是本地方法对应的栈帧,此时PC值为空
-
Java堆
1.所有线程共线Java堆
2.Java堆用于存储对象的实例
3.Java对可以处于物理上不连续的内存空间,但是逻辑上是连续的
4.堆中可以划分出多个线程私有的分配缓冲区(TLAB, Thread Local Allocation Buffer),提升对象分配时的效率(私有缓冲区满时才才在公共缓冲区分配,减少同步开销)
-
方法区
1.方法区也是线程共享的
2.方法区存储:类(型)信息、常量(常量池)、静态变量、代码缓存等数据
-
直接内存
1.直接内存并不是虚拟机运行时数据区域的一部分
2.NIO可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆里面的DirectByteBuffer对象作为这块内存的引用进行操作,从而避免了在Java堆和Native堆之间来回复制数据
3.JVM的所有内存大小并不等于物理内存大小,JVM各数据区大小可设置
关于虚拟机中对象
-
对象的创建过程
类加载 => 分配内存 => 初始化为0 => 写对象头 => 执行构造方法
-
对象的内存布局
对象在堆内存中可分为三个部分 => 对象头、实例数据、对齐填充
1.对象头:包括 a.对象的运行时数据(Mark Word):哈希码、GC分代年龄、锁状态…这部分数据长度占32bit或者54bit; b.类型指针,即对象指向它的类型元数据的指针,jvm通过该指针确定对象是哪个类的实例
2.实例数据:主要是对象的各字段的具体内容(包括继承所得的)
3.对齐填充:填充以满足“对象起始地址必须是8字节的整数倍”这一要求
-
对象的访问定位
Java程序通过栈上的reference数据来操作堆上的具体对象
reference可以是直接指针(直接指向资源)、也可以是句柄(指向资源的索引),如图所示:

注:1.“到对象类型数据的指针”实际上就是对象头中的内容; 2.直接指针访存少; 3.句柄的优势在于reference数据中存放的句柄地址稳定,对象移动时只需修改句柄中的指针