Java堆空间 - -Xmx如何正常工作?

时间:2011-08-24 16:07:59

标签: java heap out-of-memory

我在我的应用程序中遇到了臭名昭着的 OutOfMemoryException ,而不是简单地增加可用的堆空间量我试图查看问题所在,以防万一,有某种泄漏从我的申请。

我添加了JVM参数 -XX:+ HeapDumpOnOutOfMemoryError ,当遇到OutOfMemory错误时会创建堆转储。然后我分析了使用不同的分析工具生成的转储文件。然后我开始使用-Xmx参数并观察模式。

令我困惑的是以下内容。为什么在分析转储时我发现所有对象的总大小远小于我使用-Xmx参数设置的总大小? 例如,假设我将-Xmx设置为'2048m'。当我分析转储文件时,我在堆上发现了总共400Mb的对象。我期待找到2GB。我错过了什么吗?

2 个答案:

答案 0 :(得分:5)

我的猜测是,由于现代GC将堆分区为独立的内存区域(年轻/终身/永久代),因此永久生成空间完全填满内存错误就足够了。您可以使用各种JVM命令行选项配置不同生成空间的比率。

这是一篇关于Tuning Garbage Collection with the 5.0 Java[tm] Virtual Machine的好文章(我找不到更新的文章,但我认为基础知识仍适用于较新的虚拟机)。

答案 1 :(得分:3)

重新阅读您的错误消息 - 它可能会告诉您哪种类型的内存耗尽了。我猜这是PermGen的空间。 Permgen用于类定义(以及其他内容)。您可以通过 -XX调整PermGen的空间:MaxPermSize PermGen不是堆的一部分,因此不包含在堆转储中。

有关查看PermGen的更多信息,请参阅this answer

如果这不是问题,请尝试将初始堆大小(-Xms)设置为与最大值相同。这样做意味着堆不会增长,这应该让您更容易理解正在发生的事情。

我建议使用jvisualvm(JDK的一部分)在程序运行时查看内存利用率。