jol用于分析java对象内存布局,需引入0.17版jol-core依赖(scope为provided);用classlayout查单个对象结构,graphlayout查集合整体内存占用(含引用对象),辅助评估缓存合理性与字段设计优化。

直接用 JOL 查集合的内存占用,关键不是“看单个对象”,而是看清整体结构+引用关系+对齐填充。它不测运行时堆压力,但能帮你预判缓存是否划算、字段设计是否浪费。
怎么引入 JOL 工具
在 pom.xml 里加依赖(推荐 0.17 版):
<dependency></dependency><groupid>org.openjdk.jol</groupid><artifactid>jol-core</artifactid><version>0.17</version><scope>provided</scope>
注意:provided 表示仅编译/测试阶段使用,不打进生产包,避免冗余。
查单个对象内存布局(比如 VO 类)
用 ClassLayout.parseClass(YourClass.class) 看类定义层面的结构,或用 ClassLayout.parseInstance(obj) 看实际实例(含值和对齐):
- 输出里
OFF是字段起始偏移,SZ是大小(单位字节) -
(object header: mark)和(object header: class)合计通常 12 字节(开启指针压缩时) - 引用类型(如
String、Long)占 4 字节(64 位 JVM + 压缩指针),不是对象本身大小 - 最后一行
Instance size是该对象最终占用的总字节数,一定是 8 的倍数(因 JVM 对齐规则)
查整个集合(List / Map)真实内存开销
单看元素类不够——集合本身有容器开销,还要算上所有引用指向的对象实体:
- 用
GraphLayout.parseInstance(list).totalSize()得到整个对象图的**估算总内存**(含 list 结构 + 所有元素实例 + 元素内部引用的对象) - 用
GraphLayout.parseInstance(list).toFootprint()输出详细统计,例如:-
java.util.ArrayList:自身结构(数组引用 + size 等) -
[Ljava.lang.Object;:底层数组对象(存储引用的数组) -
net.xxx.IpBlacklistVO:每个 VO 实例(按Instance size累加) -
java.lang.String:VO 中字符串内容实际占用(可能远大于 4 字节引用)
-
- 特别注意:如果 VO 里有
String ip,ip字段只占 4 字节(引用),但字符串内容(char[])会单独计算,且 char[] 自身也有对象头+数组长度+数据+对齐
辅助判断本地缓存是否合理
把 JOL 分析嵌入启动或预热逻辑,快速验证缓存预期:
- 查出 1 万条
IpBlacklistVO占约 267 KB(如你日志所示),那 100 万条就约 26 MB —— 完全可放堆内,无需立刻上 Redis - 若发现某个 VO 的
Instance size异常大(比如 80+ 字节),检查是否有冗余字段、未拆分的大对象、或用了BigDecimal等重型包装类 - 对比
ArrayList和LinkedList:前者底层数组紧凑,后者每个 Node 都带前后引用,集合越大,链表额外开销越明显
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











