我故意在数据结构中添加项目,直到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
答案 0 :(得分:4)
堆分为年轻一代和老一代两部分。例如,你得到OOM老一代是完整的或支离破碎的,以至于不可能将年轻一代的对象推向旧的(可能是其他人)。
如果您使用例如日志记录GC使用情况-verbose:gc -XX:+PrintGCDetails -Xloggc:gc.log
然后你会看到每一代的尺寸。
您可以在此处查看如何调整生成大小https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/sizing.html