Java 堆空间 - -Xmx 到底如何工作?
我在我的应用程序中遇到了臭名昭著的 OutOfMemoryException ,我没有简单地增加可用堆空间量,而是尝试调查问题所在,以防万一,我的应用程序存在某种泄漏。
我添加了 JVM 参数 -XX:+HeapDumpOnOutOfMemoryError,它会在遇到 OutOfMemory 错误时创建堆转储。然后我分析了使用不同分析工具生成的转储文件。然后我开始使用 -Xmx 参数并观察模式。
让我困惑的是以下内容。为什么在分析转储时我发现所有对象的总大小远小于我使用 -Xmx 参数设置的总大小? 例如,假设我将 -Xmx 设置为“2048m”。当我分析转储文件时,我发现堆上总共有 400Mb 的对象。我本来以为能找到 2GB 的。我错过了什么吗?
I have encountered the infamous OutOfMemoryException in my application and instead of simply increasing the amount of Heap Space available I tried to look into what the problem was, just in case, there was some sort of leak from my application.
I added the JVM parameter -XX:+HeapDumpOnOutOfMemoryError which creates a Heap Dump when the OutOfMemory Error is encountered. I then analysed the dump file produced with different profiling tools. I then started playing around with the -Xmx parameter and observing patterns.
What puzzled me is the following. Why is it that on analyzing the dump I found that the total size of all objects was much less than the total that I set using the -Xmx parameter?
For example, say I set the -Xmx to '2048m'. When I analyzed the dump file I found a total of 400Mb of objects on the Heap. I was expecting to find 2GB. Am I missing something?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我的猜测是,由于现代 GC 将堆划分为单独的内存区域(年轻代/终身代/永久代),因此永久代空间完全填满就足以发生内存不足错误。您可以使用各种 JVM 命令行选项配置不同生成空间的比率。
这是一篇关于使用 5.0 Java 调整垃圾收集的好文章[tm ] 虚拟机(我找不到更新的虚拟机,但我认为基础知识仍然适用于较新的虚拟机)。
My guess is that since modern GCs partition the heap into separate memory areas (young / tenured / permanent generations), it is enough for the permanent generation space to fill up completely for an out of memory error to occur. You can configure the ratio of different generation spaces using various JVM command line options.
Here is a good article about Tuning Garbage Collection with the 5.0 Java[tm] Virtual Machine (I couldn't find a more recent one but I think the basics still apply in newer VMs).
重新阅读您的错误消息 - 它可能会告诉您耗尽了哪种类型的内存。我猜那是永久代空间。 Permgen 用于类定义(除其他外)。您可以通过 -XX:MaxPermSize 调整 PermGen 的空间。 PermGen 不是堆的一部分,因此不包含在堆转储中。
有关查看 PermGen 的更多信息,请参阅此答案。
如果这不是问题,请尝试将初始堆大小 (-Xms) 设置为与最大值相同。这样做意味着堆不会增长,这应该更容易理解发生了什么。
我建议使用 jvisualvm(JDK 的一部分)来查看程序运行时的内存利用率。
Re-read your error message - it may tell you which type of memory you ran out of. I'd guess that it was PermGen space. Permgen is used for class definitions (amongst other things). You can tune the space for PermGen via -XX:MaxPermSize PermGen isn't part of the heap, so isn't included in heap dump.
See this answer for more information on looking at PermGen.
If this isn't the issue, then try setting your initial heap size (-Xms) to the same as the maximum. Doing this means that the heap won't grow which should make understanding what's going on easier.
I recommend using jvisualvm (part of the JDK) to look at your memory utilisation as your program runs.