HotSpot虚拟机对象探秘

对象的创建过程

1、JVM遇到一条字节码new指令时
2、检查该指令是否能在常量池中定位到一个类的符号引用,并检查这个符号引用代表的类是否已被加载。

  • 2.1、如果没有加载,必须先执行相应的类加载过程。
    3、为新生对象分配内存。
  • 3.1、 采用哪种垃圾回收器,其内存分配算法是不同的;
  • 3.2、 内存分配存在并发问题,一种:采用同步或CAS的方式;第二种:在每个线程中预先分配一小块内存(称为TLAB),只有本地缓冲区用完了,分配新的缓存区时才需要同步锁定。

4、虚拟机必须将分配到的内存空间(不包括对象头)都初始化为零值。
5、JVm还要对对象进行必要的设置,如:该对象是哪个类的实例、类的元数据信息、对象hashcode、对象的GC分带年龄等信息。

对象的内存布局

1、对象头(Header)

  • 1.1、第一类用于存储对象自身的运行时数据,如hashcode、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。其长度在32-64位的虚拟机中分别为32bit或64bit,官方称为:MarkWord。
  • 1.2、第二类是类型指针:对象指向它的类型元数据的指针,JVM通过该指针确定该对象是哪个类的实例。查找对象的元数据信息并不一定要通过对象本身。
    2、实例数据(Instance Data)
    存储代码中定义的各种类型的字段内容,无论是父类继承的还是子类定义的都记录下来。
    3、对齐填充(Padding)
    仅起到占位符的作用,对象头是8个字节,实例数据如果没有对齐(不是8个倍数),就需要对齐填充来补全。

对象的访问定位

Java程序通过栈上的reference数据来操作堆上的具体对象,主流访问方式主要有使用句柄和指针两种:
句柄:
Java堆中将可能会划分出来一块内存来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自具体的地址信息。图2-2
指针:
Java堆中对象的内存布局就必须考虑如何放置访问类型数据的相关信息,reference中存储的直接就是对象地址,如果只访问对象本身,不需要多一次间接访问开销。图2-3
image
图2-2
image
图2-3

posted @ 2025-08-11 17:49  Charlie-Pang  阅读(7)  评论(0)    收藏  举报