为什么我的 Java 堆转储只显示一半的堆?

Why does my Java heap dump show only half the heap?

我有意向数据结构添加项目,直到 Java 抛出 OutOfMemoryError,并使用 -XX:+HeapDumpOnOutOfMemoryError 抓取堆转储。我正在使用 -Xmx100M,所以我预计堆转储会显示将近 100MB 的活动对象,但它只显示 46MB。

如果只有 46MB 的活动对象,为什么 Java 会抛出 100MB 堆的 OOM?

(我意识到我很可能没有提供足够的信息来回答这个问题,但我不确定什么是相关的。很高兴根据需要添加更多信息。)

编辑:-verbose:gc 输出的结尾:

 [Full GC (Ergonomics) [PSYoungGen: 1056K->64K(2560K)] [ParOldGen: 7116K->7116K(7168K)] 8173K->7180K(9728K), [Metaspace: 5981K->5981K(1056768K)], 0.0071141 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
 [Full GC (Allocation Failure) [PSYoungGen: 64K->0K(2560K)] [ParOldGen: 7116K->7075K(7168K)] 7180K->7075K(9728K), [Metaspace: 5981K->5974K(1056768K)], 0.0190392 secs] [Times: user=0.02 sys=0.00, real=0.02 secs] 
 java.lang.OutOfMemoryError: Java heap space

堆分为年轻代和老年代两部分。例如,您会得到 OOM老一代已满或碎片化,无法将对象从年轻一代提升到老一代(可能还有其他人)。

如果您使用例如记录 GC 使用情况-verbose:gc -XX:+PrintGCDetails -Xloggc:gc.log 然后你会看到每一代的大小。

您可以在此处查看如何调整生成大小 https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/sizing.html