JVM 规范中没有限制对象在内存中是怎么表示的,具体的设计方式取决于各 JVM 实现,我们就以最常见的 HotSpot 为例来说明。
HotSpot JVM 是用一种叫做 Ordinary Object Pointer(OOP)的数据结构来表示指向对象的指针。在 OOP 中,最重要的是 mark word 和klass word:
刚才说了,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>
下面我们来看看一个普通对象在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 的元素的话,也占用这么多空间
我们有这么一个类
public class SimpleInt { private int state;}