对象的内存布局分为两种:普通对象,数组对象
1. 普通对象
- 对象头,hotspot中名为markword,8byte
- ClassPointer:-XX:+UseCompressedClassPointers 为4byte,不开启为8byte
- 实例数据
- 引用类型:-XX:+UseCompressedOops 为4byte,不开启为8byte
- Oops:Ordinary Object Pointers
- Padding:8的倍数
2. 数组对象
- 对象头:markword 8byte
- ClassPointer
- 数组长度:4byte
- 数组数据
- Padding:8的倍数
3.实验
- 新建项目ObjectSize (1.8)
- 创建文件ObjectSizeAgent
public class ObjectSizeAgent {
private static Instrumentation inst;
public static void premain(String agentArgs, Instrumentation _inst) {
inst = _inst;
}
public static long sizeOf(Object o) {
return inst.getObjectSize(o);
}
}
- src目录下创建META-INF/MANIFEST.MF
- 注意Premain-Class这行必须是新的一行(回车 + 换行),确认idea不能有任何错误提示
Manifest-Version: 1.0
Created-By: wangxshen.com
Premain-Class: com.wangxshen.test.ObjectSizeAgent
- 打包jar文件
- 在需要使用该Agent Jar的项目中引入该Jar包
project structure - project settings - library 添加该jar包- 运行时需要该Agent Jar的类,加入参数:
-javaagent:D:\test\ObjectSize.jar
- 使用方法
public class SizeOfAnObject {
public static void main(String[] args) {
System.out.println(ObjectSizeAgent.sizeOf(new Object()));
System.out.println(ObjectSizeAgent.sizeOf(new int[] {}));
System.out.println(ObjectSizeAgent.sizeOf(new P()));
}
private static class P {
//8 _markword
//4 _oop指针
int id; //4
String name; //4
int age; //4
byte b1; //1
byte b2; //1
Object o; //4
byte b3; //1
}
}
4. Hotspot开启内存压缩的规则(64位机)
- 4G以下,直接砍掉高32位
- 4G - 32G,默认开启内存压缩 ClassPointers Oops
- 32G,压缩无效,使用64位
5. 一道阿里面试题!
一个String对象,里面存了"123456",这个对象占多少内存?
计算方法:
https://xie.infoq.cn/article/986ca1bcf56ac2ee9eedbd34f
答案:40 + 2 * 6 = 48字节