一、Java对象内存布局
Java对象的内存布局:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。无论是32位还是64位的HotSpot,使用的都是8字节对齐。 也就是说每个java对象,占用的字节数都是8的整数倍,(对象头 + 实例数据 + padding)% 8等于0且0 <= padding < 8。
1、基本数据类型占用的字节数,JVM规范中有明确的规定,无论是在32位还是64位的虚拟机,占用的内存大小是相同的。
2、reference类型在32位JVM下占用4个字节,但是在64位下可能占用4个字节或8个字节,这取决于是否启用了64位JVM的指针压缩参数UseCompressedOops。
3、new Object()这个对象在32位JVM上占8个字节,在64位JVM上占16个字节。
4、开启(-XX:+UseCompressedOops)指针压缩,对象头占12字节; 关闭(-XX:-UseCompressedOops)指针压缩,对象头占16字节。
5、64位JVM上,数组对象的对象头占用24个字节,启用压缩之后占用16个字节。之所以比普通对象占用内存多是因为需要额外的空间存储数组的长度。
6、对象内存布局中的实例数据,不包括类的static字段的大小,因为static字段是属于类的,被该类的所有对象共享。
7、对象头由Mark Word、指向类的指针、数组长度(只有数组对象才有)组成。
Mark Word记录了对象和锁有关的信息,当这个对象被synchronized关键字当成同步锁时,围绕这个锁的一系列操作都和Mark Word有关。Mark Word在32位JVM中的长度是32bit,在64位JVM中长度是64bit。
Mark Word在不同的锁状态下存储的内容不同,在32位JVM中是这么存的
二、Java对象大小计算
通过多内存布局的大致了解,使用jvm内存布局(jol)的小工具得出一个Java对象的大小。那么jol是个什么鬼?JOL (Java对象布局)是用于分析jvm中的对象布局的小工具箱。这些工具大量使用不安全的JVMTI和可服务性代理(SA)来解码实际的对象布局、占用空间和引用。
JOL下载地址:https://github.com/openjdk/jol
下面创建一个maven项目做个小测试:
1、在pom中加入工具依赖:
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.14</version>
</dependency>
2、编写测试代码
public class JolDemo {
private int paramInt;
private long paramLong;
private String paramString;
public static void main(String[] args) {
///获取JolDemo内存布局大小
ClassLayout classLayout = ClassLayout.parseClass(JolDemo.class);
System.out.println(classLayout.toPrintable());
}
}
3、 查看运行结果:
由布局情况可知:
对象头(objec header) 占 12bytes , int型成员变量paramInt占4bytes,long型成员变量paramLong占8bytes,引用数据paramString占4bytes,对其填充4bytes,总共32bytes
4、如果使用idea,可以安装jol插件,选中类名,右键选择 show object layout 也可直接查看