文章目录
Java对象的内存布局
Java中,一个实例对象在内存中的组成主要包括对象头、实例数据、补齐,而对象头则进一步包括markword与类型指针:
- markword:包含了锁的信息、hashcode、gc信息等等
- 大小8B
- 锁信息:无锁、偏向锁、轻量级锁、重量级锁、自旋锁
- gc信息:三色标记法标记的状态
- hashcode
- klass pointer 类型指针(有的也叫Class Metadata Address):指向对应数据类型的class,比如new Object就指向Object.class;
- 大小8B,一般默认开启指针压缩就是4B。因为大部分机器32位指针寻址就够力;
- instance data 实例数据:存放成员变量(基本数据类型就直接存储,类的实例存储其引用,比如String)
- Padding:将对象整体大小对齐为8B大小
- 因为这里说的是64位JVM,一次寻址范围64bit,即8B。
计算对象占用的内存大小
Openjdk jol
openjdk jol提供了计算对象内存布局的方法,即ClassLayout.parseInstance
。
- 引入maven依赖
<!-- https://mvnrepository.com/artifact/org.openjdk.jol/jol-core --> <dependency> <groupId>org.openjdk.jol</groupId> <artifactId>jol-core</artifactId> <version>0.16</version> </dependency>
- 使用
ClassLayout.parseInstance
public static class MyClass{ } public static void main(String[] args) { MyClass myClass = new MyClass(); System.out.println(ClassLayout.parseInstance(myClass).toPrintable()); }
来算几个
Object o = new Object() 该对象在内存中占用多少字节?
Object类本身不含成员变量,所以instance data为0,两个header word总共位8+4=12B,Padding补齐为16字节。
最终就是16B
基本数据类型作为成员变量的对象
- 含有1个int的对象:16B。instance data为4B,两个Header word(markword+klass Pointer)12B,共16B,刚好是8的倍数,不用Padding;
- 含有2个int的对象:24B。instance data为2*4=8B,两个Header word(markword+klass Pointer)12B,此时共20B,需要4B的Padding凑成8的倍数,因此共24B;
- 含有两个int一个boolean的对象:24B。instance data为2*4+1=9B,两个Header word(markword+klass Pointer)12B,此时共21B,需要3B的Padding凑成8的倍数,因此共24B;
有实例对象作为成员变量的对象
public static class MyClass{
int a;
int b;
boolean flag;
String s = "Hello";
}
public static void main(String[] args) {
MyClass myClass = new MyClass();
System.out.println(ClassLayout.parseInstance(myClass).toPrintable());
}
可以看出,由于String是另一个对象,Mycalss的instance data只存储其引用。