我在我的应用程序中遇到了臭名昭着的 OutOfMemoryException ,而不是简单地增加可用的堆空间量我试图查看问题所在,以防万一,有某种泄漏从我的申请。
我添加了JVM参数 -XX:+ HeapDumpOnOutOfMemoryError ,当遇到OutOfMemory错误时会创建堆转储。然后我分析了使用不同的分析工具生成的转储文件。然后我开始使用-Xmx参数并观察模式。
令我困惑的是以下内容。为什么在分析转储时我发现所有对象的总大小远小于我使用-Xmx参数设置的总大小? 例如,假设我将-Xmx设置为'2048m'。当我分析转储文件时,我在堆上发现了总共400Mb的对象。我期待找到2GB。我错过了什么吗?
答案 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的一部分)在程序运行时查看内存利用率。