网上结论多以32位系统为主。本文基于64位,力求简介,不会写太多废话,但能保证写出来的都是可供验证的客观事实。
验证工具:jol-cli
代码环境:64位 windows系统
Java普通对象的组成【非数组】
三部分:对象头,实例数据,对齐填充。
对象头
开启指针压缩:8 byte + 4 byte =12 byte ==> 96 bit **默认**✔
不开启指针压缩:8 byte + 8 byte =16 byte ==> 128 bit
Mark Word
64位 Win环境下,Mark Word占 8 byte ==> 64bit
此处仅讨论无锁【Normal】状态下:25 + 31 + 1 + 4 + 1 + 2 = 64 bit。
Klass 指针【指向其类的元数据的指针】
JVM通过这个指针确定对象是哪个类的实例。
- 开启指针压缩:4 byte
- 不开启指针压缩:8 byte
实例数据
对象中实实在在的数据:int 4,short 2,long 8,byte 1,char 2 ,float 4,double 8,单位byte,转bit *8。
对齐填充
JVM要求Java对象的大小必须是8 byte的整数倍,所以为了填充到整数倍,设置了对齐填充区。
证实
1 | public class TestObj { |
利用jol-cli
在main中打印出对象信息如下:
前三行为对象头,默认开启了指针压缩,所以12 byte,(一行4 byte,3行)。跟着一个int占4 byte,1行;一个short占2 byte,半行。 由于Java对象必须为8 byte的整数倍,所以灰色为对齐填充,占6 byte。
window环境下,对象头的高位是最右边,所以看对象头中Mark Word区域时候要从后往前看。
此时为无锁状态,对象头中,前25位无用,均为0。
跟着31位为HashCode值,可以看到和打印出来的HashCode和我们所料一样。
最后8位代表gc年龄、锁状态等信息。
总结
64位 开启指针压缩,对象分布如下: