Java对象内存占用该信谁?jhat还是ClassLayout?
Java对象内存占用数值差异分析与结论
优先采信**JOL(org.openjdk.jol.info.ClassLayout)**给出的32字节结果,它是基于JVM内存布局规则的精确计算,最贴近对象在堆中的实际内存占用。以下是各工具数值差异的原因:
各工具数值差异解析
JOL的32字节:
JOL直接解析对象的完整内存布局:- 对象头:64位JVM开启指针压缩时,Mark Word(8字节)+ Klass Pointer(4字节),共12字节;
- 实例数据:两个
int字段(各4字节,共8字节)+ 两个对象引用(各4字节,共8字节),总计16字节; - 对齐填充:JVM要求对象大小为8字节的倍数,12+16=28字节,向上对齐到32字节。
这个结果完整覆盖了对象在堆中占用的所有内存,是最精确的单实例内存占用值。
jhat的40字节:
jhat统计的是对象占用的堆内存块大小,而非对象本身的精确大小。JVM在堆中分配内存时,会以预设的块粒度(如16字节倍数)划分内存区域,jhat可能将对象所在的整个内存块大小计入,或者包含了JVM内部的跟踪元数据,导致统计值偏大。堆直方图的24字节:
堆直方图(jmap -histo)的统计做了简化,未包含完整的对象头。它仅计算了Klass Pointer(4字节)+ 实例数据(16字节),总计20字节,再对齐到8字节倍数得到24字节。这种统计是为了快速估算内存占用,忽略了对象头中的Mark Word部分,所以数值偏小。
总结
不同工具的统计维度和用途不同:
- JOL:用于精确分析对象内存布局,结果最可信;
- jhat:侧重堆内存块的分配情况,数值包含额外内存开销;
- 堆直方图:用于快速统计内存占用趋势,是近似值,不适合精确计算单实例大小。
内容的提问来源于stack exchange,提问作者sr-01-01
相关产品推荐
相关产品推荐

