Jetty 7:OutOfMemoryError:应用程序重新部署时的PermGen空间

时间:2011-08-05 12:54:46

标签: memory-leaks jetty out-of-memory permgen jvm-arguments

第一次应用启动正确。然后我删除webapp / * .war文件并粘贴* .war的新版本。 Jetty开始部署新战争,但发生错误java.lang.OutOfMemoryError: PermGen space。如何配置Jetty以修复错误/进行正确的重新部署?

solution对我没有帮助 Jetty版本:jetty-7.4.3.v20110701

6 个答案:

答案 0 :(得分:11)

可能无法解决问题。每个JVM都有一个PermGen内存区域,用于类加载和静态数据。每当你的应用程序被取消部署时,它的类加载器应该被丢弃,并且所有类也都被它加载。如果由于对类加载器的其他引用仍然存在而失败,那么收集类加载器和应用程序类的垃圾也将失败。

A blog entryits follow up解释了问题的可能来源。只要应用程序容器的代码使用包含对其中一个类的引用的类,就会阻止类的垃圾回收。上述博客条目中的示例是java.util.logging.Level构造函数:

protected Level(String name, int value) {
    this.name = name;
    this.value = value;
    synchronized (Level.class) {
        known.add(this);
    }
}

请注意,knownjava.util.logging.Level的静态成员。构造函数存储对所有已创建实例的引用。因此,只要从应用程序的代码中加载或实例化Level类,垃圾回收就无法删除您的类。

要解决此问题,您可以使用自己的代码避免使用所有正在使用的类,或者确保不会从代码中对类进行引用。这两个问题都可能发生在随Java提供的任何类中,因此无法在您的应用程序中修复。您无法通过仅更改自己的代码来阻止此问题!

您的选择基本上是:

  • 增加内存限制并减少错误次数
  • 按照链接博客文章中的详细说明分析您的代码,避免使用存储对象引用的类

答案 1 :(得分:7)

如果发生PermGen内存不足,则需要重新启动jvm,在你的情况下重新启动jetty。您可以使用链接解决方案中的JVM选项增加PermGen空间,以便稍后进行(稍后我的意思是:在重新部署之后)。但它会偶尔发生,你可以做到无所不能,以避免这种情况。您链接的答案很好地解释了PermGenSpace是什么以及它溢出的原因。

使用:

-XX:PermSize=64M -XX:MaxPermSize=128M

或者,如果那还不够

-XX:PermSize=256M -XX:MaxPermSize=512M

另外,如果使用此命令,请务必增加vm可用的空间量。

使用

-Xms128M -Xmx256M

答案 2 :(得分:1)

对于Jetty 7.6.6或更高版本,这可能有助于http://www.eclipse.org/jetty/documentation/current/preventing-memory-leaks.html

我们使用了AppContextLeakPreventer,它有助于因permgen空间而导致的OOM错误

答案 3 :(得分:0)

我对HotSpot也有同样的问题,但是对于没有永久代的JRockit,问题已经消失了。它现在是免费的,所以您可能想尝试一下:https://blogs.oracle.com/henrik/entry/jrockit_is_now_free_and

答案 4 :(得分:0)

看起来非常像Permanent Generation leak。每当您的应用程序在取消部署后让某些类挂起时,您就会遇到此问题。您可以尝试使用最新版本的Plumbr,也可以找到剩余的类。

答案 5 :(得分:0)

对于未来的读者(相对于提出这个问题时):

JDK 8 中,Perm Gen Space消失了(不再存在)。相反,现在Metaspace取自机器的原生空间。

如果您遇到Perm Gen Overflow问题,那么您可能需要查看this explanationthis comments on the removal process