导致 java.lang.OutOfMemoryError: PermGen space 错误的算法
我在 Sun JVM (1.6.0_21-b06) 上遇到 PermGen 空间错误(好吧,这是 Oracle :))。增加选项 -XX:MaxPermGen 值没有帮助。我知道 PermGen 是一个用于永久对象(例如类元数据)的空间。项目中的类数量不是很大~ 10 000。在崩溃之前,jvisualvm 显示 57MB 作为已使用的 PermGen。
我猜想某些算法占用了所有可访问的内存。有人知道导致 PermGen 溢出的算法示例吗?
UPD。我问这样抽象的问题,因为此刻我无法使用任何探查器 - 代码崩溃如此严重,以至于 jvisualvm 和 eclipse 停止响应。我需要使用kill -KILL {process_numer}从终端杀死java进程。我使用的是组织不良(但商业)的代码,其中包含许多线程和 JMS 消息传递。调试一团糟——我首先需要知道去哪里寻找。
I am getting PermGen space error on Sun JVM (1.6.0_21-b06) (Ok, it's Oracle :)). Increasing of option -XX:MaxPermGen value does not help. I know that PermGen is a space intended for permanent objects like class metadata. Count of classes in project is not so big ~ 10 000. Before crash jvisualvm shows 57MB as Used PermGen.
I guess that some algorithm occupies all accessible memory. Does someone know examples of algorithms that lead to PermGen overflow ?
UPD. I ask such abstract question, because in the moment I can not use any profiler - code crashes so hard that jvisualvm and eclipse stop to respond. I need than kill java processes from terminal with kill -KILL {process_numer}. I work with bad organized (but commercial) code that has many threads and JMS messaging. Debugging is a mess - I need some idea first where to look.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
与其说是算法,不如说是实现。这是一种非常愚蠢的方法来生成填充 PermGen 空间的随机字符串:
简而言之:实习字符串是一种会耗尽 PermGen 内存的东西。
It's not so much the algorithm as the implementation. Here's a really dumb way to generate random Strings that fills up PermGen space:
In short: interning Strings is one thing that can eat up PermGen memory.
有两件事可能会导致 PermGen 空间问题:
String.intern(String)
方法在 PermGen 堆中创建字符串。如果您进行了大量的驻留操作并直接(或间接)保留对驻留字符串的引用,则可以填充 PermGen。类加载器在 PermGen 堆中创建 JVM 内部类描述符和代码段。如果您的应用程序执行大量动态类加载,并且类对象没有被垃圾回收,则可以填充 PermGen。
Java Web 应用程序的热重新部署依赖于动态加载,是 PermGen 问题的常见来源。根本原因通常是内存泄漏,涉及从某个对象到旧类加载器的隐藏引用。 (Tomcat 经常因此而“陷入困境”,但真正的问题通常是在正在重新部署的 Web 应用程序中。)
据我所知,@Michael Borgwardt 提到的 Proxy 案例也是 Proxy 实现生成类文件并将其加载到的结果苍蝇。
There are two things that are likely to lead to PermGen space issues:
The
String.intern(String)
method creates Strings in the PermGen heap. If you do a lot of interning and directly (or indirectly) retain references to the interned Strings, you can fill PermGen.The classloaders creates JVM internal class descriptors and code segments in the PermGen heap. If your application does a lot of dynamic class loading, and the class objects don't get garbage collected, you can fill PermGen.
Hot redeployment of Java webapps relies on dynamic loading and is a common source PermGen problems. The root cause is typically a memory leak that involves a hidden reference from some object to an old classloader. (Tomcat often gets "stick" for this, but the real problem is typically in the webapp that is being redeployed.)
AFAIK, the Proxy case mentioned by @Michael Borgwardt is also a result of the Proxy implementation generating class files and loading them on the fly.
是的,但这有什么意义呢?如果您想修复此问题,请安装内存分析器工具(例如 jprobe 或 lambda 探针)并检查内存泄漏发生的位置,然后修复该问题。
现在举个例子:有数千种方法可以超过永久代空间。当我们继承一个使用 JMS 的应用程序时,我注意到一个项目。 jms 连接保持打开状态,应用程序在收到大量请求后几分钟内崩溃,并出现与您遇到的类似错误。需要注意的是:当我们从 jboss 迁移到 weblogic(迁移到 beajrockit)时,令人惊讶的是它自行修复了,或者至少承受了技术债务的打击。我的建议是无论如何,应该首先修复具有内存泄漏的错误代码,然后修补应用程序服务器和堆空间分配参数。
这是一个有用的链接,其中包含有关您收到的异常的一些信息。
http://www.jroller.com/agileanswers/entry/preventing_java_s_java_lang
编辑
这个链接可能有帮助
http://www.precisejava.com/javaperf/j2ee/JMS.htm
Yes but what is the point of this? if you want to fix this install a memory profiler tool like jprobe or lambda probe and check where the memory leak is happening, and fix that.
Now for the example: There are thousands of ways to exceed perm gen space. I had noticed on a project when we inherited an application where they were using JMS. The jms connections were left open, the application crashed within a few minutes after it got a lot of requests with a similar error like you are getting. Point to note: when we moved to weblogic from jboss (moved to beajrockit) amazingly it fixed itself or atleast took the blow of technical debt. My advice would be irrespective of this, bad code with memory leaks should be fixed first, then tinker with app servers and heap space allocation paramters.
Here is a useful link with some information on the exception you are getting.
http://www.jroller.com/agileanswers/entry/preventing_java_s_java_lang
EDIT
This link may be helpfull
http://www.precisejava.com/javaperf/j2ee/JMS.htm
如果您使用 java.lang.reflect.Proxy< /a> 非常密集,这也可能会耗尽你的 PermGen 空间。
If you use java.lang.reflect.Proxy very intensively, that could eat up your PermGen space as well.
查看内存分析器 - http://www.eclipse.org/mat/。它是一个java转储内存分析器。在发生意外错误后,它非常有用。
Check out memory analyzer - http://www.eclipse.org/mat/. It is a java dump memory analyzer. It is pretty useful after an unexpected error.
您是否使用不同的垃圾收集器?
检查 此页面。
Are you using a different garbage collector?
Check some instructions on this page.