最直接有效的方式是用jol工具,它能清晰展示对象内存分布、字段偏移、对齐填充及浅层/深层大小;需添加maven依赖并调用classlayout.parseinstance(obj).toprintable()输出布局详情。

最直接有效的方式是用 JOL(Java Object Layout)工具,它能清晰展示对象在 JVM 中的内存分布、各字段偏移量、对齐填充,以及精确的浅层大小(shallow size)和深层大小(retained size)。
JOL 工具的基本使用
添加 Maven 依赖即可开始分析:
然后调用 ClassLayout.parseInstance(obj).toPrintable() 打印完整内存布局:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 输出包含每字段的内存偏移(OFFSET)、占用字节(SIZE)、类型(TYPE)和描述(DESCRIPTION)
- 末尾会明确标出 Instance size(对象自身占用的总字节数,含对齐填充)
- 还会提示 Space losses(内部/外部浪费字节数),帮助识别字段排列是否紧凑
关键影响因素必须确认
JVM 参数直接影响对象大小,尤其是指针压缩是否开启:
- 64 位 HotSpot 默认开启
-XX:+UseCompressedOops(堆 ≤32GB 时),此时 klass pointer 占 4 字节;关闭后升为 8 字节 - 对象头大小随之变化:开启时为 12 字节(8 字节 Mark Word + 4 字节 klass pointer),关闭时为 16 字节
- 数组对象额外多 4 字节长度字段,且头更大(开启压缩为 16 字节,关闭为 24 字节)
- 所有对象最终大小强制 8 字节对齐,不足则补 padding
区分浅层大小与深层大小
同一对象,不同方法返回值含义不同:
-
VM.current().sizeOf(obj)返回的是浅层大小 —— 仅当前对象实例本身,不含引用指向的其他对象 -
GraphLayout.parseInstance(obj).toFootprint()可计算深层大小 —— 当前对象 + 所有独占引用的对象(递归去重) - 例如
new ArrayList<string>()</string>的浅层大小约 24 字节,但若存了 10 个字符串,深层大小就远超此数
替代方案与注意事项
除了 JOL,还有两种方式可获取浅层大小,但限制更多:
-
Instrumentation.getObjectSize():需通过 Java Agent 启动,适合监控场景,但无法获取字段级布局 -
jdk.nashorn.internal.ir.debug.ObjectSizeCalculator:已废弃,不推荐用于新项目 - JOL 底层也依赖 Instrumentation,但它封装了可视化输出和字段分析能力,实用性远高于裸调用
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










