我有一个用大约60-70个端点编写的大型Spray API,我使用Java 7上的spray-can HTTP服务器运行它。在运行大量针对它的自动端到端测试时,我收到了java.lang.OutOfMemoryError:PermGen空格错误。
我设法通过强制卸载类来解决问题(使用-XX:+ CMSClassUnloadingEnabled),将Max PermGen大小增加到1024m并将线程堆栈大小设置为2m。但我担心我会掩饰我的问题。
我的问题是:
我认为PermGen存储了类元数据。我可以理解在编译代码时如何耗尽PermGen空间。但是在这种情况下,我没有在机器上编译代码,如上所述,这个错误让我在运行应用程序时花了几分钟。为什么呢?
我采取了正确的方法处理PermGen空间错误吗?是 推荐使用Spray-Can运行的应用程序的JVM标志?
使用CMSClassUnloadingEnabled时,是否还需要在Java 7中使用UseConcMarkSweepGC?这个问题 (CMSPermGenSweepingEnabled vs CMSClassUnloadingEnabled) 似乎表明它适用于Java 6.
答案 0 :(得分:1)
框架中的某些东西 - 或者无论如何都是代码 - 可能是动态创建类(代理等)。我建议您在运行一段时间后分析应用程序的堆转储,或者最好在崩溃OutOfMemoryError之后分析。关于如何创建转储的说明可以在我的this博客文章中找到。分析说明可能仅部分适用于您的情况。在找到正在填充PermGen的之后,我们可以尝试确定是否需要修复/阻止泄漏,或者应用程序是否只是大的。
是的,对于-XX:+ CMSClassUnloadingEnabled具有任何效果,您还需要使用-XX启用并发标记和扫描垃圾收集器:+ UseConcMarkSweepGC。然而,默认的GC(通常是较旧的JVM中的Parallell和较新的1.7+中的G1)默认情况下会进行类卸载,即使Parallell GC中似乎存在与此相关的错误。