Java堆空间 -Xmx参数的工作原理是什么?

8
我在应用程序中遇到了臭名昭著的OutOfMemoryException,并且尝试查看问题所在,以防止应用程序存在某种泄漏。而不是简单地增加可用的堆空间量。我添加了JVM参数-XX:+HeapDumpOnOutOfMemoryError,当遇到OutOfMemory Error时会创建一个Heap Dump。然后,我使用不同的分析工具分析生成的转储文件。之后,我开始玩弄-Xmx参数并观察模式。
令我困惑的是以下内容。为什么在分析转储时,我发现所有对象的总大小要比我使用-Xmx参数设置的总大小小得多?
例如,假设我将-Xmx设置为'2048m'。当我分析转储文件时,在Heap上找到了400MB的对象总数。我原本期望找到2GB。我错过了什么吗?

你检查过你的 OOME 是否确实提到了堆内存吗?有一些(相对不常见的)情况下,会抛出 OOME,但并非堆内存已满。 - Joachim Sauer
1
没错,@Joachim,JVM中线程过多会导致x86崩溃,并出现OOM异常。 - aalku
2个回答

5
我的猜测是,由于现代GC将堆分成不同的内存区域(年轻/ tenured / permanent generations),因此permanent generation space完全填满就足以导致内存不足错误。您可以使用各种JVM命令行选项配置不同生成空间的比例。
这里有一篇关于Tuning Garbage Collection with the 5.0 Java[tm] Virtual Machine的好文章(我找不到更新的文章,但我认为基础知识在新的VM中仍然适用)。

3
重新阅读您的错误信息 - 它可能会告诉您您耗尽了哪种类型的内存。我猜它是PermGen空间。PermGen用于类定义(以及其他事情)。您可以通过 -XX:MaxPermSize 来调整PermGen空间。 PermGen不是堆的一部分,因此不包括在堆转储中。
有关查看PermGen的更多信息,请参见此答案
如果这不是问题,则尝试将初始堆大小(-Xms)设置为最大值。这样做意味着堆不会增长,这应该使理解正在发生的情况更加容易。
我建议使用jvisualvm(JDK的一部分)观察程序运行时的内存利用率。

可能会有趣...是的,我得到的错误是这个。现在正在尝试,完成后会回复结果。 - Kros
使用了-XX:MaxPermSize后,一直遇到问题。我认为我的应用程序最新的更改导致了超过阈值引起异常。感谢您的帮助。 - Kros

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接