JVM内存区域
Java虚拟机运行时数据区
Java堆
所有线程共享,是虚拟机内存中最大的一块,也是最常GC的地方,此区存放对象实例和数组。
Java堆可以处于物理上不连续的内存空间中,但在逻辑上它应该被是为连续的。
TLAB:即每个线程在Java堆中预先分配一小块内存,哪个线程要分配内存,就在哪个线程的本地缓冲区分配
方法区
所有线程共享,存储类型信息、常量、静态变量、基石编译器编译后的代码缓存等数据
运行时常量池
方法区的一部分
常量池主要用来存放两大类常量:字面量和符号引用量,字面量相当于Java语言的常量,如文本字符串,声明为final的常量等,符号引用包括以下三种
- 类和接口的全限定名
- 字段名称和描述符
- 方法名称和描述符
Java虚拟机栈
线程私有,生命周期与线程相同。每个方法被执行的时候,Java虚拟机都会同步创建一个栈帧,用于存储局部变量表,操作数栈,动态连接,方法出口等信息。每一个方法被调用直至执行完毕的过程,就对应着栈帧在虚拟机栈中从入栈到出栈的过程,我们说的栈通常更多的是指虚拟机栈中局部变量表部分
局部变量表存放了编译期可知的各种的各种基本数据类型(Boolean、byte、char、short、int、float、long、double)
本地方法栈
本地方法栈与虚拟机栈所发挥的作用是非常相似的,其区别知识虚拟机栈为虚拟机执行Java方法服务,而本地方法栈则是为虚拟机使用到的本地方法服务
程序计数器
程序私有,保存当前线程执行字节码的行号指示器,可以使线程切换的时候保存上下文
如果执行的是java方法,计数器报存字节码指令地址
如果执行的是本地native方法,计数器为空(undefine)
唯一一个在JAVA虚拟机规范中没有规定任何OOM情况的区域
对象创建过程
对象的内存布局
对象头
存储对象自身的运行时数据,如哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳
类型指针:虚拟机通过这个指针来确定对象是哪个类的实例,如果对象是一个数组,那么对象头中还必须有一块用于记录数组长度的数据
实例数据
程序代码里面所定义的各种类型的字段内容,无论是从父类继承下来的,还是在子类中定义的字段必须记录起来
对齐填充
占位符,虚拟机自动内存管理系统要求对象的大小必须是8字节的整数倍,如果对象实例数据没有对齐,就需要通过对齐填充来补全