美文网首页
Hotspot虚拟机对象揭秘

Hotspot虚拟机对象揭秘

作者: jqdywolf | 来源:发表于2018-03-31 15:17 被阅读0次

    Hotspot虚拟机对象揭秘

    这部分我们主要分三部分:对象的创建、对象的内存布局、对象的访问定位。这里说的都是堆。

    对象的创建

    虚拟机遇到new指令:

    1. 检查类是否已被加载
      检查指令的参数是否可以在常量池中定位到一个类的符号引用,且检查这个符号引用代表的类是否已被加载。如果没有执行类加载过程。
    2. 为生成的对象分配内存
      对象的大小在类加载后已被确定。
      目前主流的是两种分配方式:指针碰撞和空闲列表。
      指针碰撞:即堆内存是规整的,分配内存就是移动临界指针而已。
      空闲列表:对内存不是规整的,虚拟机维护一个空闲内存列表。
      具体哪种方式由堆采用的GC是否带有压缩整理功能决定。

      这里引出一个多线程下线程安全问题:多个线程同时分配内存时,可以出现同一块内存分配给多个对象。如何解决?
      两种方案:使用CAS操作和本地线程分配缓冲。
      CAS就不说了,本地线程分配缓冲:就是说堆中都会为每个线程预先分配一小块内存(TLAB),当需要生成对象时,先使用这块内存,用完了再使用其他堆内存(需要同步锁定)。

    3. 将内存空间初始化零值
    4. 设置对象头的信息
    5. 执行init方法,即构造器方法。

    对象的内存布局

    即堆中每个对象的内存布局。
    我们都知道分为三部分:对象头+实例数据+填充数据。
    对象头=Mark Word + 指向元数据指针 (+ 数组长度)
    2/3个虚拟机位数长度
    Mark Word:GC分代信息+HashCode+锁信息。
    上面都已经是我们知道的。
    注意的两点:

    • 实例数据的布局
      Hotspot默认布局:相同宽度的字段总被分配到一起。(long/double int short/char byte)在满足这个前提下,父类出现在子类前面。
    • 填充数据
      Hotspot虚拟机要求对象的起始地址必须是8字节(64 bit)的整数倍。即对象的大小必须是8字节的整数倍。

    对象的访问定位

    即栈中的引用如何找到堆中对象以及方法区中的元数据。
    两种方式:句柄访问和直接指针。

    • 句柄访问


      句柄访问
    • 直接指针


      指针指针

      句柄访问的优点:对象被移动,引用无感知
      直接指针的优点:相比较于句柄访问少了一次内存访问。效率高。HotSpot用的是这个。

    相关文章

      网友评论

          本文标题:Hotspot虚拟机对象揭秘

          本文链接:https://www.haomeiwen.com/subject/hebgcftx.html