【对象头】JVM 中的对象结构
1 前言
Java 本身是面向 OOP 编程的,我们代码中创建的对象经过编译装载进我们的 JVM 中,那么我们的实例对象在 JVM 中具体表现的结构是什么样的呢,就是我们这节要看的东西。
2 工具
在了解之前我们要看到实际的东西,就是我们可能知道有对象头、实例数据、对齐,但是这毕竟是概念,我们怎么看到具体真实的数据呢,把下边这个 jar包引入自己的工程:
https://repo.maven.apache.org/maven2/org/openjdk/jol/jol-cli/0.9/,找到 jol-cli-0.9-full.jar,然后引入到自己的工程中。
涉及的 JVM 参数:
- -XX:+UseCompressedOops:开启压缩指针,如果JVM的版本在 Java SE 6 update 23 及以上, 则不需要再设置
-XX:+UseCompressedOops
参数, 因为默认会开启。 - -XX:-UseCompressedOops:关闭压缩指针
- 压缩指针:顾名思义可能节省内存开销吧
示例代码:
public static void main(String[] args) { Person person = new Person("狗子", 1, Boolean.TRUE); //打印虚拟机的信息 System.out.println(VM.current().details()); //打印对象大小 System.out.println(ClassLayout.parseInstance(person).instanceSize()); //打印对象头大小 System.out.println(ClassLayout.parseInstance(person).headerSize()); //打印对象信息 System.out.println(ClassLayout.parseInstance(person).toPrintable()); }
3 对象在内存的结构
那么我们有了工具,其实大概能看出来一个对象在内存中的组成:
由3部分组成:
- 对象头:对象头又可以划分三部分:Mark Word、Class Pointer、数组长度
- 实例数据:从上边我们的例子中可以看到就是我们成员变量占用的字节数,小细节:static 修饰的不会存在这里
- 对齐字节:对齐倍数的补充字节
这里我们主要看下对象头:
- Mark Word: 存储对象自身的运行数据;
- Class Pointer: 类指针也就是当前对象所引用的类的地址即是哪个类的对象,因为我们的Class文件装载进JVM中放到方法区, 会是一个C++对象也叫KClass对象,所以这里也叫Klass Word;
- 数组长度:当对象是数组的时候使用;
我们平时使用的 Synchronized java内置锁,锁对象可以是任意对象,锁的信息其实就是存放到了 Mark Word 中,在 JDK 1.6 之前,内置锁都是重量级锁,效率低下。在 JDK 1.6 之后为了提高 synchronized 的效率,才引入了偏向锁、轻量级锁。
针对 Mark Word,如果JVM是32位,则Mark Word是32bit;如果64位,则Mark Word是64bit。我们这里以64位的详细来看下:
4 小结
这节我们简单看了下我们的对象在 JVM 中的结构组成,主要的就是对象头中的东西,涉及到了我们平时用到的锁,我们下节针对这几种锁展开细致的讲解,有理解不对的地方欢迎指正哈。