是什么导致JBoss上的PermGen OutOfMemoryError?


8

JBoss中PermGen OutOfMemoryError的根本原因是什么?

我在开发环境中运行JBoss AS 4.2.2,这是在大量重新部署Web应用程序之后发生的。

Christian Vest Hansen的博客提供了JVM选项,这些选项很有帮助,但不能完全解决问题:

-XX:+UseConcMarkSweepGC
-XX:+CMSPermGenSweepingEnabled
-XX:+CMSClassUnloadingEnabled
-XX:MaxPermSize=128m

Answers:


5

如前所述,您可能正在遇到泄漏的类加载器。由于某些原因,您的课程未卸载。发生这种情况有两个原因

  • 所述类的对象仍然存在于堆中,对象始终引用其类,或者
  • 类加载器在某处被引用,无论出于何种原因,类加载器都引用其类,以便不会两次加载它们

这个问题没有万能的解决方案。一个有助于您找到根本原因的有用工具是Eclipse Memory Analyzer Tool,您可以将其应用于JVM中的堆转储(可以使用-XX:+ HeapDumpOnOutOfMemoryError选项在OOM上启用堆转储)。也许开始从您的Web应用程序中查找java.lang.Class对象,以了解为什么它们一直处于活动状态。不幸的是,PermGen通常不是JVM堆转储的一部分,因此您只能尝试在其余堆中查找相关的工件(如果我没记错的话,Class-objects不会存储在PermGen中,请仅提供实际的字节码,请如果我错了,请纠正我)。

HTH。

编辑:
Dave Cheney在评论中建议java.lang.Class对象确实是PermGen的一部分,并且不包含在常规热点堆转储中。除非您有一个在堆转储中写入此信息的JVM,否则您将需要其他方法。您仍然可以查找对象的实例,但是如果泄漏类/类加载器(不幸的是,它们都相互暗示),则似乎需要查找其他符号(来自JBoss的元数据对象等)。


1
我很确定Class对象存储在PermGen中(即,作为Class实例的对象)。Sun JVM上有一个单独的区域,称为代码缓存,该区域存储了已编译为机器代码的代码。PermGen和代码缓存都是Non Heap内存的一部分,您可以使用jconsole之类的工具看到它们
Dave Cheney

@戴夫·切尼:你是对的。卡在PermGen中的泄漏的Class对象通常是导致OP问题的原因。
艾迪(Eddie)'2009年

鱼卵,虽然我不认为PermGen的内容会写到堆转储中(这是使用Sun JVM,但我对其他人没有太多经验),但是hprof转储格式当然知道诸如此类加载了类,多少个类加载器等。在Eclipse Memory Analyser中打开hprof时,您可以看到此信息。可能没有写的是组成Java字节代码的大型二进制类数据,您在堆转储中看到的是存储在PermGen上的Class实例的“存根”。
戴夫·切尼

2

根本原因是对已丢弃的类的引用,这些类泄漏到其类装入器之外,从而阻止JVM从perm gen卸载这些类。您使用的那些标志可能会导致JVM主动清除卸载的类,但不会解决根本问题。

这是一个很好,abeit复杂的解释在这里


1

PermGen OutOfMemory错误的原因是重新部署了应用程序。根本原因是重新部署后PermGen中的Class对象泄漏。

当然,解决方法是在重新部署一定数量后重新启动JVM。

这是一个很难解决的难题,尽管您可以通过一些侦查来做出很大的改进。从这里开始:停止Web应用程序时,请确保:

  • 您启动的所有线程均已停止
  • 您启动的所有线程池均已关闭
  • 您可以释放的所有静态引用都被释放

这些是一些可能导致Class对象陷入PermGen的事情。

另外,请注意,并非所有的JVM(或所有版本的JVM)都将在PermGen中使用GC类对象。如果运行的不是PermGen中的GC类对象的JVM或JVM版本,则唯一的选择是在重新部署一定数量后重新启动JVM。鉴于您提到的JVM选项,这可能不适用于您。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.