java.lang.OutOfMemoryError:Web 应用程序使用上的 PermGen 空间
我正在努力解决最近出现的内存不足 PermGen 问题。出现错误时保存的日志片段之一:
java.lang.OutOfMemoryError: PermGen space
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
at org.apache.felix.framework.ModuleImpl$ModuleClassLoader.findClass(ModuleImpl.java:1872)
at org.apache.felix.framework.ModuleImpl.findClassOrResourceByDelegation(ModuleImpl.java:720)
at org.apache.felix.framework.ModuleImpl.access$300(ModuleImpl.java:73)
at org.apache.felix.framework.ModuleImpl$ModuleClassLoader.loadClass(ModuleImpl.java:1733)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
我增加了最大永久大小 -XX:MaxPermGen=128m
但这只是一个临时解决方案,因为我很确定我们面临一些内存泄漏这里。我们应用程序的 Web 部分部署在 jetty 上(jsf +icefaces)。单击随机组件会增加使用的内存 - 我正在使用 jstat -gcold 进行监控,几乎每次点击都意味着增加 3-4kb。我已将 -XX:+TraceClassLoading
添加到 jvm 参数,并看到许多 sun.reflect.GenerateConstructorAccessor
和 sun.reflect.GenerateMethodAccessor
被记录当网页用户界面上有任何操作时。当 99% 的 permgen 被使用时,我还做了一个堆转储。我使用 YourKit profiler 来分析堆。在类加载器选项卡中,有许多 sun.reflect.DelegatingClassLoader
行,每行有 1 个类。是什么导致内存不断增长?任何帮助将非常感激。
提前致谢, 卢卡斯
I am struggling with an outOfMemory PermGen issue that has been showing up recently. One of the log snippets that was saved when error appeared:
java.lang.OutOfMemoryError: PermGen space
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
at org.apache.felix.framework.ModuleImpl$ModuleClassLoader.findClass(ModuleImpl.java:1872)
at org.apache.felix.framework.ModuleImpl.findClassOrResourceByDelegation(ModuleImpl.java:720)
at org.apache.felix.framework.ModuleImpl.access$300(ModuleImpl.java:73)
at org.apache.felix.framework.ModuleImpl$ModuleClassLoader.loadClass(ModuleImpl.java:1733)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
I've increased max perm size -XX:MaxPermGen=128m
but this is just a temporary solution because I am preety sure we are facing some memory leak here. The web part of our applications is deployed on jetty (jsf + icefaces). Clicking on random components increases the memory used - I am monitoring it with jstat -gcold
and nearly every hit means 3-4kb more. I've added -XX:+TraceClassLoading
to the jvm params and see many sun.reflect.GeneratedConstructorAccessor
and sun.reflect.GeneratedMethodAccessor
being logged when there is any action on the web user interface. I also made a heap dump when 99% of permgen was used. I used YourKit profiler to analyze the heap. In the class loader tab there are loaads of sun.reflect.DelegatingClassLoader
rows with 1 class for each. What might be causing the memory to constantly grow? Any help will be really appreciated.
thanks in advance,
Lukasz
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
在 Sun JVM 上,对属性和方法的反射访问最初是通过 JNI 调用 JVM 实现来执行的。如果 JVM 注意到某个方法或字段被反射大量访问,它将生成字节码来执行相同的操作 - 这种机制称为“膨胀”。初始速度会受到影响,但之后运行速度会快 20 倍。如果你进行大量反思,那就是一个巨大的胜利。
该字节码存在于 DelegatingClassLoader 实例创建的类中并占用永久代空间。如果出现问题,您可以通过将系统属性 sun.reflect.inflationThreshold 设置为 0(零)来关闭通货膨胀。
On the Sun JVM, reflective access to properties and methods is initially performed by calling through JNI into the JVM implementation. If the JVM notices that a method or field is being accessed by reflection a lot, it will generate bytecode to do the same thing -- a mechanism that it calls "inflation". This has an initial speed hit, but after that runs about 20 times faster. A big win if you do a lot of reflection.
That bytecode lives in classes created by DelegatingClassLoader instances and take up permgen space. If it is a problem, you can turn inflation off by setting the system property sun.reflect.inflationThreshold to 0 (zero).
首先,这与 JSF 没有具体关系。与网络应用程序的需求相比,您只是为应用程序服务器提供了太少的内存。对于所有其他在幕后使用良好反射镜头的框架,您都会遇到同样的问题(想想所有那些 EL 解决方案)。这可以是 JSF、Wicket、Spring-MVC 甚至普通的 JSP/Servlet。对于严重依赖 EL 解析器(例如 JSF(和其他))的基于组件的 Web 框架,这种机会更大。
此外,众所周知,当您过于频繁地(热)重新部署时,基于 Tomcat 的服务器也可能会导致此问题。通过以下链接了解它以及如何处理它:
First of all, this is not specifically related to JSF. You're simply giving your appserver too little memory as compared to the needs of your webapp. You would have the same problem with every other framework which uses under the covers a good shot of reflection (think of all those EL resolvings). This can be JSF, Wicket, Spring-MVC and even plain JSP/Servlet. The chance is only bigger on component based web frameworks which rely heavily on EL resolvers, such as JSF (and others).
Further it's known that Tomcat (-based) servers may cause this as well when you (hot)redeploy a bit too often. Get yourself through the following links to learn about it and how to deal with it:
我建议使用 Eclipse MAT 并遵循 本教程专门讨论 permgen 问题。
尽管达菲莫注意到您在分析问题方面做得很好,但问题的根源似乎仍然未知。也许它只是组件之一,一些解析器(如 jwenting 所建议的)或类似的。该问题并不一定意味着您需要从堆栈中丢弃 JSF。
I would suggest using Eclipse MAT and to follow this tutorial dedicated to permgen problems.
Although as duffymo noticed you've done a great job analyzing the problem, the very origin of the problems seems still unknown. Maybe it's just one of the components, some parser (as jwenting suggests) or similar. The problem doesn't necessarily mean you need to throw away JSF from the stack.
首先,感谢您对这个问题进行了如此彻底的调查,并且更好地写出了您的问题。如果每个人都像您一样有才华和优秀的作家,世界(和这个网站)将会变得更加美好。
我想您已经找到了答案:我认为 JSF 及其反射的使用是您的问题。
这就是我像躲避瘟疫一样避开 JSF 的原因之一。
在我看来,JSF 是 Struts 的一个失败的扩展。我认为 HTML/CSS/JavaScript/AJAX UI 的功能与 JSF 一样强大,甚至更强大,而且对我的 JVM 的负担要小得多。 UI 调用服务并保持良好状态并与服务器端分离。
First of all, kudos to you for doing such a thorough job of investigating this and an even better job of writing your question. The world (and this site) would be a better place if everyone was as talented and as good a writer as you are.
I think you've already found the answer: I think JSF and its use of reflection is your problem.
This is one reason why I avoid JSF like the plague.
In my opinion, JSF is a failed extension of Struts. I'd consider an HTML/CSS/JavaScript/AJAX UI to be as capable as JSF, if not more so, and far less taxing on my JVM. The UI calls services and stays nice and separate from the server side.
Permgen 问题通常是由某些进程执行大量 String.intern() 操作引起的。
一些 XML/HTML 生成器和解析器就犯了这个错误。
先看看那里,你可能很快就能找到罪魁祸首。
Permgen problems are usually caused by some process doing a LOT of String.intern() operations.
Some XML/HTML generators and parsers are guilty of this.
Look there first, you may hit on the culprit quickly.