如何获取Java对象的大小
文章目录
- 1. 使用 `java.lang.instrument.Instrumentation`(精确计算)
- 2. 使用第三方库(简化实现)
- 2.1. `jol-core`(Java Object Layout)
- 2.2. Apache Commons Lang
- 3. 手动估算(基于JVM规范)
- 4. 注意事项
- 5. 工具推荐
- 总结
1. 使用 java.lang.instrument.Instrumentation
(精确计算)
这是最准确的方法,但需要通过Java Agent来实现:
- 创建一个Java Agent类:
import java.lang.instrument.Instrumentation;public class ObjectSizeAgent {private static volatile Instrumentation globalInstrumentation;public static void premain(String agentArgs, Instrumentation inst) {globalInstrumentation = inst;}public static long getObjectSize(Object obj) {if (globalInstrumentation == null) {throw new IllegalStateException("Instrumentation not initialized");}return globalInstrumentation.getObjectSize(obj);}
}
-
配置
MANIFEST.MF
:- 在
MANIFEST.MF
中添加:Premain-Class: com.example.ObjectSizeAgent
- 在
-
打包为JAR并运行:
java -javaagent:objectsizeagent.jar YourMainClass
-
在代码中使用:
public class Main {public static void main(String[] args) {MyClass obj = new MyClass();long size = ObjectSizeAgent.getObjectSize(obj);System.out.println("Object size: " + size + " bytes");}
}
2. 使用第三方库(简化实现)
2.1. jol-core
(Java Object Layout)
由OpenJDK团队开发,可直接计算对象大小:
import org.openjdk.jol.info.ClassLayout;public class ObjectSizeCalculator {public static void main(String[] args) {MyClass obj = new MyClass();System.out.println(ClassLayout.parseInstance(obj).toPrintable());}
}
依赖(Maven):
<dependency><groupId>org.openjdk.jol</groupId><artifactId>jol-core</artifactId><version>0.16</version>
</dependency>
2.2. Apache Commons Lang
SerializationUtils.serialize()
可估算序列化后的大小:
import org.apache.commons.lang3.SerializationUtils;public class ObjectSizeEstimator {public static void main(String[] args) {MyClass obj = new MyClass();byte[] bytes = SerializationUtils.serialize(obj);System.out.println("Serialized size: " + bytes.length + " bytes");}
}
3. 手动估算(基于JVM规范)
对象在内存中的结构通常包括:
- 对象头(Object Header):
- Mark Word(通常8字节)
- 类型指针(4或8字节,取决于是否开启指针压缩)
- 实例数据(Instance Data):字段的实际值
- 对齐填充(Padding):按8字节对齐
示例计算:
class MyClass {int a; // 4字节long b; // 8字节String c; // 引用类型:4或8字节
}
- 总大小估算:
- 对象头:12字节(8+4,假设开启指针压缩)
- 实例数据:4(
a
) + 8(b
) + 4(c
) = 16字节 - 对齐填充:4字节(总大小需为8的倍数)
- 总计:12 + 16 + 4 = 32字节
4. 注意事项
-
指针压缩(Compressed OOPs):
- 64位JVM默认开启,对象引用占4字节(否则占8字节)。
- 通过
-XX:+UseCompressedOops
控制。
-
数组和集合:
- 数组对象包含额外的长度字段。
- 集合类(如
ArrayList
)需计算内部数组的大小。
-
静态字段:
- 静态字段不属于对象实例,不计入对象大小。
5. 工具推荐
- JProfiler:可视化工具,直接查看对象大小。
- YourKit:支持内存分析和对象大小统计。
- Eclipse Memory Analyzer (MAT):分析堆转储文件。
总结
- 精确计算:使用
Instrumentation
或jol-core
。 - 快速估算:手动计算对象头、字段和对齐填充。
- 复杂场景:借助专业工具分析堆内存。
一般场景下推荐 方案2