美文网首页
二(2)HotSpot虚拟机对象探秘

二(2)HotSpot虚拟机对象探秘

作者: 洪延波 | 来源:发表于2017-02-24 19:17 被阅读0次

    深入探讨HotSpot虚拟机在JAVA堆中对象分配,布局和访问的过程.

    对象创建过程

    这里说的创建对象是不包括数组和Class对象的.

    1.首先检查这个类是否已被加载,解析和初始化过.如果没有,那必须先执行相应的类加载过程.

    1. 接下来为新生对象分配内存.对相关所需内存的大小在类加载完成后便可完全确定.
    2. 内存分配完成后,虚拟机需要将分配到的内存空间全都初始化为零值.(不包括对象头),如果使用TLAB这一工作也可以提前至TLAB分配时进行.
    3. 接下来虚拟机要对对象进行必要的设置,例如这个对象是哪个类的实例,如何才能找到类的元数据信息,对象的哈希码,对象的GC分代年龄等信息,这些信息放在对象头中,
    4. 执行init方法.按照程序员的意愿进行初始化.

    对象的内存布局

    对象在内存中存储的布局可以分为三块区域:对象头(header) ;实例数据(Instance Data)和对齐填充(Padding).

    • 对象头共有两部分内容,一部分是MarkWord,根据标志位的不同被用来存储不同的内容,包括:哈希码,GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID,偏向时间戳等,对象头的另外一部分是类型指针,只想他的类元数据的指针.但是并不是所有的虚拟机实现都必须在对象数据上保留类型指针.另外如果对象是数组,那再对象头中还必须有一块用于记录数组长度的数据.
    • 实例数据部分是对象真正存储的有效信息,无论是父类继承下来的,还是子类中定义的都需要记录下来.存储顺序会受到虚拟机分配策略参数和字段在JAVA源代码中定义顺序的影响.
    • 对齐填充部分并不是必然存在的,仅仅是为了占位作用,因为HotSpot的自动内存管理系统要求对象起始地址必须是8字节的整数倍,就是说对象的大小必须是8字节的整数倍.因此这部分内容就是为了凑整.

    对象的访问定位

    对象的访问方式会因虚拟机的实现而不同,目前主流的有使用句柄和直接指针两种.

    • 如果使用句柄访问的话,那么JAVA堆中将会划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址.而句柄中包含了对象实例数据与数据各自的地址信息.

    句柄两部分分别指向堆内存中的对象数据和方法区中的类型数据

    • 如果使用直接指针访问,那么reference会直接指向堆中的对象实例,而对象中包含了一个指向方法区类型数据的指针.
      两种方式各有优势,HotSpot使用的是指针方式,因为节省了一次指针定位的时间,更快.但是使用句柄,当对象被移动时(垃圾回收)只会修改句柄中的实例指针,而reference本身不需要修改.

    虚拟机参数

    • -Xms 堆内存最小值
    • -Xmx 堆内存最大值
    • -Xoss 本地方法栈大小 但是实际上在HotSpot当中是不区分本地方法栈和虚拟机方法栈的 所以不会有效果的.
    • -Xss 栈容量设置
    • -XX:MaxPermSize 最大方法区值
    • -XX:PermSize 方法区大小

    相关文章

      网友评论

          本文标题:二(2)HotSpot虚拟机对象探秘

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