深入理解Java虚拟机之对象探秘

131 阅读2分钟

对象创建

熟悉了Java的内存区域,今天我们来了解下对象的创建:new Object()

类加载

当虚拟机遇到一个new指令的时候,首先去检查这个指令的参数能否在常量池中定位到一个类的符合引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化,如果没有,需要先执行类加载过程。

内存分配

在类加载检查通过后,接下来虚拟机将在堆上为对象分配内存,有如下两种分配方式:

  • 指针碰撞(Bump the Pointer)
    如果Java堆中内存是绝对规整的,已分配内存与空闲空间分割开来,分配内存时只需将指针向空闲空间移动一段与对象大小相等的距离。

  • 空闲列表(Free List)
    如果Java堆中的内存并不是规整的,就无法使用指针碰撞,虚拟机需要维护一个空闲内存列表,分配内存时从这个列表中找到一块足够大的空间划分给对象实例,并更新列表记录。

如何防止并发分配

由于对象创建在虚拟机上是非常频繁的行为,可能会出现同一块内存空间分配给了不同的对象。解决这个问题,有以下两种方案:

  • 采用CAS加失败重试方式

  • 将分配的动作按照线程划分在不同的空间之中进行,即为每个线程在堆中预先分配一段内存空间,称为本地线程分配缓冲(Thread Local Allocation Buffer,TLAB),分配内存时在TLAB上分配,只有当TLAB用完并分配新的TLAB时,才需要同步锁定。可以通过-XX:+/-UseTLAB来设置虚拟机是否使用TLAB。

对象初始化

内存分配完成后,虚拟机需要将分配的内存空间都初始化为0值(不包括对象头)。然后设置对象头信息,如对象的哈希码、对象的GC分代年龄、锁状态标志等。设置完对象头后,会接着执行init方法,按照程序员的意愿进行初始化,这样一个对象就被new出来了。

如果读完觉得有收获的话,欢迎点赞、关注、加公众号【Java在线】,查阅更多精彩历史!!!