JOL是Oracle官方推荐的轻量级工具,能直观显示对象在堆中的字节分布,不依赖运行时代理,适合调试阶段快速验证;通过ClassLayout.parseInstance(obj).toPrintable()可打印含OFFSET、SIZE、INSTANCE SIZE等字段的完整内存布局,例如空Object占16字节。

调试时直接调用 Object 自身方法无法获取内存占用详情,因为 equals、hashCode、toString 等方法不暴露内存布局;真正有效的分析需借助 JVM 工具链与对象结构知识,而非单纯依赖 Object API。
看对象头和对齐填充:用 JOL(Java Object Layout)打印内存布局
JOL 是 Oracle 官方推荐的轻量级工具,能直观显示对象在堆中的字节分布。它不依赖运行时代理,适合调试阶段快速验证。
- 添加 Maven 依赖:
<dependency><groupId>org.openjdk.jol</groupId><artifactId>jol-core</artifactId><version>0.17</version></dependency> - 在 debug 断点处插入代码:
String s = ClassLayout.parseInstance(yourObject).toPrintable();<br>System.out.println(s);
- 输出包含 OFFSET(偏移)、SIZE(大小)、VALUE(值)、INSTANCE SIZE(总字节数)等字段——例如空 Object 占 16 字节:对象头 12 字节(Mark Word 8 + 压缩类指针 4)+ 对齐填充 4 字节
查实际堆内大小:用 Instrumentation 获取精确字节数
这是唯一能返回“对象自身占用堆内存”准确数值的官方机制,但需提前配置 Java Agent。
- 写一个
premain类,暴露静态方法getObjectSize(obj) - 启动时加参数:
-javaagent:path/to/your-agent.jar - 在 debug 模式下,把光标停在变量上 → 右键 Evaluate Expression → 输入
ObjectSizeFetcher.getObjectSize(myObj),即可实时看到字节数 - 注意:该值不含其引用的其他对象(如 ArrayList 内部数组),只算当前对象实例本身
判断是否被 GC 回收:结合 finalize 和引用链分析
虽然 finalize() 已被标记为 deprecated,但若项目中仍存在重写,它可能干扰对象生命周期,造成“假存活”。调试时要重点排查。
立即学习“Java免费学习笔记(深入)”;
- 在可疑类的
finalize()中加断点或日志:System.out.println("finalizing: " + this); - 触发一次手动 GC(仅限测试):
System.gc();,观察该方法是否被调用 - 若调用后对象仍可被访问(比如被赋给了 static 集合),说明发生了“复活”,此时用 jmap dump + MAT 查引用链,定位强引用源头
- 检查 Finalizer 队列积压:执行
jstat -gc <pid>,若 FGC 频率低但老年代持续上涨,大概率是终结器阻塞
观察引用关系:用 IDE 的内存视图辅助定位存活路径
现代 IDE(IntelliJ IDEA / Eclipse)在 debug 时支持“View as Collection”“Show Referrers”等功能,可替代部分 MAT 操作。
- 在 Variables 面板中右键目标对象 → 选择 “View as” → 可选 Map、List 或自定义格式,快速查看内容结构
- 右键 → “Find Actions” → 输入 “Show Referrers”,列出所有强引用它的变量(包括 static 字段、线程局部变量等)
- 若发现某个 static 缓存持有大量对象,且未及时清理,就是潜在泄漏点
- 配合 “Heap Walker” 插件(IDEA Ultimate)可进一步展开引用链,比手写代码更直观


















