【JVM 常识总结 -1】JVM 内存模型
【JVM 常识总结 -2】HotSpot 虚拟机对象
【JVM 常识总结 -3】垃圾收集策略与算法
对象的内存布局
- 头对象(Header)
- 实例数据(Instance Data)
- 对齐填充(Padding)
头对象
头对象记录了对象在运行过程中所须要应用的一些数据:
- 哈希码
- GC 分代年龄
- 锁状态标记
- 线程持有的锁
- 偏差的线程 ID
- 偏差的工夫戳
对象头可能蕴含类型指针,通过该指针能确定对象属于哪个类。如果对象是一个数组,那么对象头还会包含数组长度。
实例数据
实例数据局部就是成员变量的值,其中包含父类成员和本类成员变量。
对齐填充
用于确保对象的总长度为 8 字节的数据倍。
HotSpot VM 的主动内存管理系统要求对象的大小必须是 8 字节的整数倍。而对象头局部正好是 8 字节的倍数(1 倍或 2 倍),因而,当对象实例数据局部没有对齐时,就须要通过对齐填充来补全。
对齐填充并不是必然存在的,也没有特地的含意,它仅仅起着占位符的作用。
对象的创立过程
类加载查看
虚拟机在解析 .class
文件时,若遇到一条 new 指令,首先他会去查看常量池中是否有这个类的符号援用,并查看这个符号援用所代表的类是已被加载、解析和初始化过。如果没有,如果没有则必须先执行类的加载过程。
为新生对象分配内存
对象所需内存的大小在类加载实现后便齐全确定,接下来从堆中划分一块对应大小的内存空间给新的对象。调配堆内存有两种形式:
- 指针碰撞
如果 Java 堆中内存相对规整(阐明采纳的是“复制算法”或“标记整顿法”),闲暇内存和已应用内存两头搁置着一个指针作为分界点指示器,那么分配内存时只须要把指针向闲暇内存移动一段与对象大小一样的间隔,这种调配形式称为“指针碰撞”。
- 闲暇列表
如果 Java 堆中内存并不规整,已应用的内存和空间内存交织(阐明采纳的是标记 - 革除法,有碎片),此时没方法简略进行指针碰撞,VM 必须保护一个列表,记录其中哪些内存块闲暇可用。调配之时从闲暇列表中找到一块足够大的内存空间划分给对象实例。这种形式称为“闲暇列表”。
初始化
调配完内存当前,为对象成员变量赋上初始值,设置对象头信息,调用对象的构造函数办法进行初始化。
致辞,整个对象的创立过程就实现了。
对象的拜访形式
所有对象的存储空间口都是在堆中调配的,然而这个对象的援用确是在 Java 栈中的本地变量表中调配的。也就是说在创立一个对象时两个中央都分配内存,在堆中调配的内存是理论建设这个对象,
句柄拜访形式
堆中须要有一块叫做“句柄池”的内存空间,句柄中蕴含了对象实例数据与类型数据各自的具体地址信息。
援用类型的变量寄存的是该对象的句柄地址(reference)。拜访对象时,首先须要通过援用类型的变量找到该对象的句柄,而后依据句柄中对象的地址找到对象。
间接指针拜访形式
援用类型的变量间接寄存对象的地址,从而不须要句柄池,通过援用可能间接拜访对象。但对象所在的内存空间须要额定的策略存储对象所属的类信息的地址。