背景知识

JVM 规范中没有限制对象在内存中是怎么表示的,具体的设计方式取决于各 JVM 实现,我们就以最常见的 HotSpot 为例来说明。

HotSpot JVM 是用一种叫做 Ordinary Object Pointer(OOP)的数据结构来表示指向对象的指针。在 OOP 中,最重要的是 mark word 和klass word:

  1. mark word 中包含了唯一标识一个对象的hashcode,关于锁的信息,GC的信息。mark word占用4字节(32位架构中,64位架构中是8字节),其中关于锁的信息,在对象使用偏向锁和普通锁的时候,存储方式是完全不同的。
  2. klass word则存储了一些编程语言层面的类相关的信息,比如类名,修饰符,父类信息等等。通常有4字节大小。

刚才说了,OOP中最重要的是mark word 和klass word,因为不管指向的是个普通对象,还是一个array,这两部分都是存在的。

除此之外,对于array来说,另外还要存array的长度;根据整个对象头的大小不同,还可能有一些用于对齐的填充字节。

调试环境

相关代码可以在这里找到

想直观的观察到具体的内存结构,我们需要使用JOL这个工具,添加jol-core这个依赖就可以了。

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

GET HANDS DIRTY

下面我们来看看一个普通对象在JVM中到底是怎么表示的,执行这段代码

System.out.println(VM.current().details());

可以看到以下输出

# Running 64-bit HotSpot VM.
# Objects are 8 bytes aligned.
# Using compressed oop with 3-bit shift.
# Using compressed klass with 3-bit shift.
# Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
# Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

意思也挺直白,告诉我们运行环境是64位的HotSpot虚拟机,对齐长度是8字节。我们重点看后面两行,表示的是各类型占用的内存空间。按照顺序,后面两行意思就是: 1. 对象的引用是4字节、boolean和byte占用1字节、short和char占用2字节、int和float占用4字节、long和double占用8字节 2. 如果我们把对象放到array里,作为array 的元素的话,也占用这么多空间

Class Layout

我们有这么一个类

public class SimpleInt {    private int state;}