JVM 虚拟机中的对象

本文将以 HotSpot 虚拟机为例,介绍虚拟机是如何管理对象的。

一、对象的创建

1. 类检查

当 JVM 遇到一条 new 指令时,首先检查能否在常量池中定位到类的符号引用,其次检查类是否已被加载、解析和初始化,如果没有,则先执行类的加载过程。

2. 分配内存

当类检查通过后,首先需要划分内存,即将一块确定大小的内存块从堆中划分出来

  • 假如堆中的内存都是绝对规整的,已被使用的区域和未被使用的区域被界限严格分离开,那么只需要将界限移动便可以实现内存划分,这种划分方式被称为 “指针碰撞”
  • 假如堆中的内存不是规整的,已被使用的区域和未被使用的区域交错在一起,则 JVM 需要维护一个用于指示空间使用情况的 “空闲列表”,划分时需要从列表中找到一个足够大的区域划分给对象,并更新 “空闲列表”

3. 初始化为零值

内存划分完成后,JVM 需要将划分到的内存空间都初始化为零值。这步操作保证了对象的属性能够在 Java 代码中不赋初值直接使用。

4. 对象头设置

对对象进行必要的设置,包括:对象所属的类、类元数据信息的寻找方式、对象哈希码等,这些信息会被存储在对象头中。

5. 对象初始化

执行对象的构造方法,完成对象的初始化。

二、对象的内存布局

对象的存储布局可以划分为三个部分:

  • 对象头:

    • 对象自身的运行时数据:哈希码、GC 分代年龄、锁状态标志、线程持有的锁、偏向线程 ID、偏向时间戳等
    • 类型指针:指向类型元数据
    • 数据长度:如果对象是一个数组,则还有数组长度数据,以便 JVM 确定数组长度
  • 实例数据

  • 对齐填充:不一定存在,仅起占位作用

    因为 HotSpot 虚拟机的自动内存管理系统要求对象起始地址必须是 8 字节的整数倍,因此需要使用对齐填充将对象的大小填充为 8 的整数倍

三、对象的访问定位

Java 程序会通过栈上的对象引用来操作堆上的具体对象。

具体请看:

JVM 引用 - 通过引用访问对象

参考

  • 深入理解 Java 虚拟机