如何检查Java堆是否碎片化?

时间:2019-07-05 14:30:11

标签: java jvm heap-dump fragmentation

我有一个29G堆转储,由OutOfMemoryError发生后由Hotspot VM创建。堆分析器(我使用YourKit)显示所有对象(包括不可达对象)都占用26G。我的猜测是剩余的3G被浪费了,因为堆是零散的。有没有办法检查这个理论?

1 个答案:

答案 0 :(得分:3)

这与堆碎片无关。

大小的差异由堆转储格式解释。请注意,堆转储不是堆的原始内容,而是以HPROF格式对内容进行序列化表示。

因此,每个对象实例都由具有以下结构的s记录表示:

HPROF_GC_INSTANCE_DUMP

考虑一个u1 record tag u8 object ID u4 stack trace serial number u8 class ID u4 number of bytes that follow u1* <field data> 的实例。在64位压缩的OOPs HotSpot JVM中,java.lang.Integer的实例占用16个字节:8个字节的标头+ 4个字节的类指针+ 4个字节的Integer字段。同一实例在堆转储中将占用29个字节,从而产生81.25%的巨大开销。

当然,在典型的Java应用程序中,堆通常充满了更大的对象,即数组。这就是为什么HPROF记录标头的平均开销看起来较小(大约10%)的原因,就像您的情况一样。