11

我正在努力解决最近出现的 outOfMemory 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 参数中,当 Web 用户界面上有任何操作时,我会看到许多参数并被记录下来sun.reflect.GeneratedConstructorAccessorsun.reflect.GeneratedMethodAccessor当使用 99% 的 permgen 时,我还进行了堆转储。我使用 YourKit profiler 来分析堆。在类加载器选项卡中sun.reflect.DelegatingClassLoader,每行有 1 个类。什么可能导致内存不断增长?任何帮助将不胜感激。

在此先感谢,卢卡斯

4

5 回答 5

5

在 Sun JVM 上,对属性和方法的反射访问最初是通过 JNI 调用到 JVM 实现中来执行的。如果 JVM 注意到一个方法或字段被反射访问了很多,它会生成字节码来做同样的事情——它称为“膨胀”的机制。这有一个初始速度命中,但之后运行速度大约快 20 倍。如果您进行大量反思,将是一个巨大的胜利。

该字节码存在于由 DelegatingClassLoader 实例创建的类中并占用 permgen 空间。如果这是一个问题,您可以通过将系统属性 sun.reflect.inflationThreshold 设置为 0(零)来关闭通货膨胀。

于 2012-01-09T13:54:13.837 回答
4

首先,这与 JSF 没有特别的关系。与 webapp 的需求相比,你只是给你的 appserver 提供了太少的内存。对于在幕后使用良好反射镜头的所有其他框架,您都会遇到同样的问题(想想所有那些 EL 解析)。这可以是 JSF、Wicket、Spring-MVC 甚至是普通的 JSP/Servlet。只有在严重依赖 EL 解析器的基于组件的 Web 框架上机会更大,例如 JSF(和其他)。

此外,众所周知,当您过于频繁地(热)重新部署时,Tomcat(基于)服务器也可能导致这种情况。通过以下链接了解它以及如何处理它:

于 2011-02-21T15:31:37.483 回答
3

我建议使用Eclipse MAT并按照本教程专门讨论 permgen 问题

尽管 duffymo 注意到您在分析问题方面做得很好,但问题的根源似乎仍然未知。也许它只是组件之一,一些解析器(如 jwenting 建议的那样)或类似的。这个问题并不一定意味着您需要从堆栈中丢弃 JSF。

于 2011-02-21T13:59:17.987 回答
1

首先,感谢您对这个问题进行了如此彻底的调查,并且更好地编写了您的问题。如果每个人都像你一样有才华和优秀的作家,世界(和这个网站)会变得更美好。

我想您已经找到了答案:我认为 JSF 及其对反射的使用是您的问题。

这就是我避免 JSF 像瘟疫一样的原因之一。

在我看来,JSF 是 Struts 的失败扩展。我认为 HTML/CSS/JavaScript/AJAX UI 与 JSF 一样强大,如果不是更多的话,而且对我的 JVM 的负担要少得多。UI 调用服务并保持良好并与服务器端分开。

于 2011-02-21T12:49:18.863 回答
0

Permgen 问题通常是由某些进程执行大量 String.intern() 操作引起的。一些 XML/HTML 生成器和解析器犯了这个罪。先看看那里,你可能会很快找到罪魁祸首。

于 2011-02-21T13:35:08.953 回答