Jetty 7:应用重新部署时出现OutOfMemoryError: PermGen空间错误

5
第一次应用程序正确启动。然后我删除了webapp/*.war文件并粘贴了新版本的*.war。Jetty开始部署新的war,但出现了错误java.lang.OutOfMemoryError: PermGen space。我该如何配置Jetty来修复错误/进行正确的重新部署?
这个解决方案对我没有帮助。 Jetty版本:jetty-7.4.3.v20110701
6个回答

11

可能没有办法通过配置来解决这个问题。每个JVM都有一个PermGen内存区域,用于类加载和静态数据。当应用程序被取消部署时,其类加载器应被丢弃,并且所有由它加载的类也应该被丢弃。如果其他对类加载器的引用仍然存在,导致这种丢弃失败,则垃圾回收类加载器和应用程序类也将失败。

一篇博客文章随后的跟进解释了问题可能的来源。无论何时应用程序容器的代码使用持有对你的类引用的类,都会阻止你的类的垃圾回收。所述博客条目中的例子是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中提供的任何类中,因此无法在您的应用程序内修复。您不能仅通过修改自己的代码来防止该问题发生!
您的选择基本上有两种:
  • 增加内存限制并使错误更少地发生
  • 根据链接的博客文章详细分析您的代码,并避免使用存储对您的对象引用的类

有关如何检测罪犯类的任何指导方针吗? - Erik Kaplun
1
很抱歉,我没有简单的步骤可以跟随。您可以尝试普通的堆转储并检查其中的意外对象。对它们的引用可能会给您足够的线索来发现泄漏。您还可以在 Eclipse 的内存分析器中找到一个有用的搜索工具:https://www.eclipse.org/mat/ - Augustus Kling
答案已编辑,因为http://blogs.oracle.com/fkieviet/entry/classloader_leaks_the_dreaded_java被移动到http://frankkieviet.blogspot.hu/2006/10/classloader-leaks-dreaded-permgen-space.html和http://blogs.oracle.com/fkieviet/entry/how_to_fix_the_dreaded被移动到http://frankkieviet.blogspot.hu/2006/10/how-to-fix-dreaded-permgen-space.html。感谢注意,@sasfalvi-tamás - Augustus Kling

7
如果发生PermGen内存不足错误,您需要重新启动jvm,在您的情况下重新启动jetty。您可以使用链接解决方案中的JVM选项增加PermGen空间,以便这种情况稍后发生(稍后是指:在更多重新部署之后)。但它会偶尔发生,您几乎无法避免。您链接的答案很好地解释了PermGenSpace是什么以及为什么会溢出。
-XX:PermSize=64M -XX:MaxPermSize=128M

或者,如果这还不够
-XX:PermSize=256M -XX:MaxPermSize=512M

此外,如果您使用这些命令,请务必增加虚拟机的可用空间。使用。
-Xms128M -Xmx256M

1

0

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

JDK 8中,永久代空间已经消失了(不再存在)。现在有一个叫做Metaspace的东西,它是从机器的本地空间中获取的。

如果您遇到了永久代溢出的问题,那么您可能需要查看this explanationthis comments on the removal process


0

0

看起来非常像永久代泄漏。每当您的应用程序在卸载后留下一些类挂在那里时,就会出现这个问题。您可以尝试最新版本的Plumbr,也许它会找到剩余的类。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接