JBoss 中 PermGen OutOfMemoryError 的根本原因是什么?
我在开发环境中运行 JBoss AS 4.2.2,在多次重新部署 Web 应用程序后出现了这种情况。
Christian Vest Hansen 的博客提供有助于很多,但不能彻底解决问题:
-XX:+UseConcMarkSweepGC
-XX:+CMSPermGenSweepingEnabled
-XX:+CMSClassUnloadingEnabled
-XX:MaxPermSize=128m
答案1
正如前面提到的,你可能遇到了类加载器泄漏。出于某种原因,你的类没有被卸载。这可能有两个原因
- 所述类的对象仍然存在于堆中,对象始终引用其类,或者
- 类加载器在某处被引用,无论出于什么原因,类加载器都会引用它们的类,以便不加载它们两次
这个问题没有万能的解决方案。一个可以帮助你找到根本原因的工具是Eclipse 内存分析工具,您可以将其应用于 JVM 的堆转储(您可以使用 -XX:+HeapDumpOnOutOfMemoryError 选项在 OOM 上启用堆转储)。也许可以开始从您的 Web 应用程序中寻找 java.lang.Class 对象,以了解它们为何保持活动状态。不幸的是,PermGen 通常不是 JVM 堆转储的一部分,因此您只能尝试在堆的其余部分中查找相关工件(如果我没记错的话,Class 对象不存储在 PermGen 中,只有实际的字节码才存储在其中,如果我错了,请纠正我)。
嗨嗨。
编辑:
Dave Cheney 在评论中表示,java.lang.Class-objects 确实是 PermGen 的一部分,并不包含在正常的热点堆转储中。除非您有一个将此信息写入堆转储的 JVM,否则您需要采用不同的方法。您仍然可以查找对象的实例,但如果您泄漏了类/类加载器(不幸的是,它们都暗示了对方),您似乎需要寻找其他迹象(来自 JBoss 的元数据对象等)。
答案2
根本原因是对已丢弃的类的引用泄漏到类加载器之外,从而阻止 JVM 从永久代卸载这些类。您使用的这些标志可能会导致 JVM 积极清除是但它不能解决根本问题。
有一个很好的解释,虽然很复杂这里
答案3
PermGen OutOfMemory 错误的原因是应用程序重新部署。根本原因是重新部署时 PermGen 中泄漏了 Class 对象。
当然,解决方法是在一定次数的重新部署后重新启动 JVM。
这是一个很难完全解决的问题,尽管通过一些侦查,你通常可以取得很大的进步。你可以从这里开始:当你的 Web 应用停止时,请确保:
- 全部您发起的话题已停止
- 全部您启动的线程池已关闭
- 全部可以释放的静态引用已被释放
这些是可能导致 Class 对象被困在 PermGen 中的一些因素。
另请注意,并非所有 JVM(或所有版本的 JVM)都会在 PermGen 中 GC Class 对象。如果您正在运行不会在 PermGen 中 GC Class 对象的 JVM 或 JVM 版本,那么您唯一的选择是在重新部署一定次数后重新启动 JVM。这大概考虑到您提到的 JVM 选项,并不适用于您。