Hotspot虚拟机对象探秘

时间:2023-01-02 12:08:48

对象的创建

虚拟机在遇到一条new指令时,首先去检查这条指令的参数能否在常量池中定位到一个类的符号引用,并检查该类是否被加载过。如果没有,先执行类加载的过程。

类加载检查完成之后,接下来虚拟机为新生对象分配内存。对象所需要的内存大小在类加载完成之后就可以完全确定,为对象分配内存的任务等同于把一块大小确定的内存从Java堆中划分出来。假设Java堆中内存是绝对规整的,所有用过的内存都放在一边,空闲的内存放在一边,中间放着一个指针作为分界点的指示器,分配内存就仅仅是把指针向空闲空间那边挪动一段与对象大小相等的距离。

除了如何划分可用空间之外,还有另一个需要考虑到的问题是对象创建是十分频繁的行为,即使是仅仅修改一个指针指向的位置,在并发情况下也不是线程安全的。解决这个问题有两种方案。第一中是:实际上虚拟机采用CAS配上失败重试的方式保证操作的原子性。第二种是为每个线程在Java堆中预先分配一快内存,称为本地线程分配缓冲。

内存分配完成之后,虚拟机需要将分配到的内存空间都初始化为零。这步操作保证了对象的实例字段在Java代码中可以不赋予初值就可以直接使用。

接下来,虚拟机要对对象进行必要的设置,例如这个对象是哪个类的实例,如何才能找到类的元数据信息,对象的哈希码,对象的GC分代年龄信息。这些信息存放在对象的对象头中。

在上面工作完成之后,从虚拟机的角度来看,一个新的对象已经产生了,但是,从Java程序的角度来看,对象创建才刚刚开始-----<init>方法还没有执行,所有的字段还都是零。所以,一般来说,执行new方法之后,就会紧接着执行<init>方法,把对象按照程序员的一员进行初始化,这样一个真正可以使用的对象才算完全产生出来。