java.lang.OutOfMemoryError:web应用程序使用的PermGen空间

java.lang.OutOfMemoryError:web应用程序使用的PermGen空间,java,jsf,memory-leaks,icefaces,permgen,Java,Jsf,Memory Leaks,Icefaces,Permgen,我正在努力解决最近出现的outOfMemory永久性问题。出现错误时保存的日志片段之一: java.lang.OutOfMemoryError: PermGen space at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632) at java.lang.ClassLoade

我正在努力解决最近出现的outOfMemory永久性问题。出现错误时保存的日志片段之一:

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)
我增加了max perm size
-XX:MaxPermGen=128m
,但这只是一个临时解决方案,因为我确信我们在这里面临一些内存泄漏。我们的应用程序的web部分部署在jetty(jsf+icefaces)上。点击随机组件会增加内存使用量——我用
jstat-gcold
监控它,几乎每次点击都意味着3-4kb。我已经将
-XX:+TraceClassLoading
添加到jvm参数中,并看到许多
sun.reflect.GeneratedConstructorAccessor
sun.reflect.GeneratedMethodAccessor
在web用户界面上有任何操作时被记录。在使用99%的permgen时,我还进行了堆转储。我使用YourKit分析器来分析堆。在类加载器选项卡中有
sun.reflect.DelegatingClassLoader
行的load,每个行有一个类。是什么导致记忆不断增长?任何帮助都将不胜感激

提前感谢,,
卢卡斯

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

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

这就是我像躲避瘟疫一样避开JSF的原因之一


在我看来,JSF是Struts的一个失败的扩展。我认为HTML/CSS/JavaScript /Ajax UI可以像JSF一样有能力,如果不是这样的话,我JVM的征税就要少得多。UI调用服务并保持良好状态,与服务器端分开

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

我建议使用和跟随


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

首先,这与JSF没有特别的关系。与webapp的需要相比,您只是给appserver的内存太少了。如果其他框架在封面下使用了一个很好的反射镜头,那么你就会遇到同样的问题(想想所有这些EL resolvings)。这可以是JSF、Wicket、springmvc,甚至是普通的JSP/Servlet。只有在严重依赖EL解析器(如JSF等)的基于组件的web框架上,这种可能性才更大

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


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


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

在增加MaxPermGen之前,它的值是多少?Jvm使用了默认值84mb。我也尝试了MAT,但这基本上与你的工具箱显示的一样多——Sun.Real.AdvutialCultLooper-Enter感谢你,但是我们现在太远了,甚至无法考虑改变Web框架。错误的印象。在JSF出现之前就存在perm gen问题。struts/tiles 1.x系列存在永久性泄漏。其他框架也是如此。关于不同原因的文章很多。它们都指向的一个主要点是孤立的对象/类,由于与其他类加载器工件的链接,这些对象/类不能被GBed。因此,您会遇到鸡和蛋的问题,从而防止类/对象被GCed和内存泄漏。谷歌搜索各种文章,看看你的代码或你正在使用的任何第三方代码是否“应受谴责”。这不是错误的印象。当然,没有JSF,perm-gen问题也会发生。我只是碰巧看到了一个特别糟糕的JSF实现,它使得用日晷计时页面刷新成为可能。我建议像避免瘟疫一样避免它。我喜欢新来的人在1.5年前的问题上做出这种无聊的评论。我只是有一种奇怪的感觉,不管我给永久一代分配多少记忆,它仍然能够把它堵起来——至少它的行为方式让我这么认为。部署应用程序后,permgen的使用率为60%。浏览所有组件(以便基本上加载所有类)后,permgen的使用率将达到65%左右。然后,在squish自动化测试的帮助下,我很容易将使用率提高到近80%。我猜所有基于反射的加载类都是一种期望行为,只是不知道为什么它们不被卸载。这些事情总是让我想:.NET也遭受同样的痛苦吗?他们使用分代GC算法;它们的字符串是不可变的;他们有反省。他们能感受到我们的痛苦吗?他们怎么办?我开发了一个部署在WebLogic上的应用程序,它从不需要重新启动服务器:没有泄漏,没有连接丢失。应用服务器是唯一的di吗