JVM系列之对象深度探秘

起笔

最近的一段时间的精神有点萎靡,导致前两篇文章写的不尽人意,所以就休息了一段时间再来更新文章。

在这里插入图片描述
参考书籍:“深入理解java虚拟机”

个人java知识分享项目gitee地址:Cornucopia

个人java知识分享项目github地址:Cornucopia

对象的内存布局

在这里插入图片描述

在HotSpot虚拟机中,对象的内存布局分为一下3块区域:

  • 对象头(Header)
  • 实例数据(Instance Data)
  • 对齐填充(Padding)

对象头中包含了类型指针(Class Pointer),通过改指针能确定对象属于那个类。如果对象是数组对象那么对象头中还会包含数组的长度。

对象头(Header)

在HostSpot虚拟机对象的对象头部分包含了两类信息:

  • 用于存储对象自身的运行时数据,如哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等,这部分数据的长度在32位和64位的虚拟机中分别为32bit和64bit(8byte),官方称它为“Mark World”

  • 对象头的另外一部分是类型指针,即对象指向它的类型元数据的指针(Class Pointer),Java虚拟机通过这个指针来确定该对象是那个类的实例。此外,因为虚拟机可以通过普通Java对象的元数据信息确定Java对象的大小,但是如果数组的长度是不确定,将无法通过元数据的信息推断出数组的大小。因此,如果对象是一个数组,那么对象头中还必须有一块用于记录数组长度的数组,也就是上图中的Data Length。

实例数据(Instance Data)

实例数据是对象真正存储的有效信息,即我们在程序代码里面所定义的各种类型的字段内容,无论是从父类继承下来的,还是在子类中定义的字段都必须记录起来。

对齐填充(Padding)

对齐填充并不是必然存在的,也没有特别的含义,它仅仅起占位符的作用。那为什么要有这么一段数据是因为HotSpot虚拟机的自动内存管理系统要求对象起始地址必须是8byte的整数倍,换句话说就是任何对象的大小都必须是8字节的整数倍。对象头部分已经被精心设计成正好是8byte的倍数(1倍或者是2倍),因此,如果对象实例数据部分没有对齐的话,就需要通过对齐填充来补全。

分析案例

我们已经有对象内存布局的理论知识,现在,我们通过一个案例来加深一下印象:

案例:

new user();在内存中一共占多少个字节?

public class user {
   private String name;
   private int age;
}
解析

在开始之前,我们需要创建一个maven项目,然后引入JOL工具包

<dependency>
    <groupId>org.openjdk.jol</groupId>
    <artifactId>jol-core</artifactId>
    <version>0.16</version>
</dependency>

执行代码:

public class ObjectTest {
    public static void main(String[] args) {
        System.out.println(ClassLayout.parseInstance(new user()).toPrintable());
    }
    static class user {
        private String name;
        private int age;
    }
}


JVM参数:

打印被设置的参数 : -XX:+PrintCommandLineFlags

结果:

JVM参数打印:

-XX:InitialHeapSize=268435456 -XX:MaxHeapSize=4294967296 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC 

终端输出内容:
在这里插入图片描述

我们来分析一下,首先看jvm参数中的XX:+UseCompressedClassPointers ,我们知道它开启了指针压缩(也就是会压缩ClassPointer的内存大小,从8byte->4byte),那么,按照上面我们掌握的理论知识,一个对象内存包含三个部分,对象头为固定的8byte,ClassPointer如果开启了指针压缩则是4byte,Instance Data这里user中包含了一个int对象占4byte,String是一个引用对象固定占4byte,也就是Instance Data总共占8byte,由于Padding是占位符,我们先不分析,这里对象头和对象数据总共占 8+4+8=20,这里20不是8的倍数,由于jvm的内存管理的限制,这里jvm会将padding按找距离20byte最少的8的倍数进行填充,也就是24byte,padding就是4byte(即图中的 (object alignment gap) 所占的byte大小)。

  • 19
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 14
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值