我在 Sun 的 JRE6 中运行 Tomcat6,每对部署者都会遇到 OutOfMemoryException:永久代。我已经完成了 PermGen 解决方案的谷歌搜索并尝试了许多修复。没有工作。我读到了很多关于 Oracle 的 JRockit 的好文章,以及它的 PermGen 分配如何达到巨大的大小(与 Sun 的 128M 相比),虽然它不能解决问题,但它允许我在 PermGen 异常之间重新部署 100 次,而不是 2 次。现在。

JRockit 的问题是要在生产中使用它,您需要购买 WebLogic,这要花费数千美元。还有哪些其他(免费)选项对 PermGen 扩展更宽容?下面的 JVM 在这方面表现如何?

  • IBM JVM
  • 打开JDK
  • 布莱克当
  • 咖啡店

...其他的?

更新: 有人问为什么我认为 PermGen max 是 128M。原因是因为每当我尝试将其提高到 128M 以上时,我的 JVM 都无法初始化:

[2009-06-18 01:39:44] [info] Error occurred during initialization of VM [2009-06-18 01:39:44] [info] Could not reserve enough space for object heap [2009-06-18 01:39:44] [395 javajni.c] [error] CreateJavaVM Failed

奇怪的是,它尝试为对象保留空间失败 , ,尽管我不确定它是“the”堆而不是“a”堆。

我使用 1024MB 初始堆和 1536MB 最大堆启动 JVM。

我将关闭这个问题,因为它已经得到回答,即。“切换是没有用的”并询问 为什么我的 Sun JVM 在 PermGen 设置较大时会失败?

有帮助吗?

解决方案

我同意 Michael Borgwardt 的观点,即您可以增加 PermGen 大小,但我不同意这主要是由于内存泄漏造成的。PermGen 空间被大量使用反射的应用程序大量占用。因此,基本上,如果您有一个在 Tomcat 中运行的 Spring/Hibernate 应用程序,请准备好大幅增加 PermGen 空间。

其他提示

是什么让您想到 Sun 的 JVM 仅限于 128M PermGen?您可以使用 -XX:MaxPermSize 命令行选项自由设置;默认为64M。

然而,问题的真正原因可能是应用程序中的内存泄漏,它阻止了类被垃圾收集;这些可能非常微妙,特别是当涉及类加载器时,因为它所需要的只是对任何地方的任何类的单个引用。 本文 详细描述问题,并且 这个 建议修复它的方法。

从技术上讲,“PermGen”内存池是 Sun JVM 的东西。其他 JVM 并不这么称呼它,但它们都有一个或多个非堆内存池的想法。

但是,如果您的 Sun JVM 中存在 permgen 问题,那么迁移到另一个 JVM 不太可能解决任何问题,它只会以不同的名称显现出来。

如果多次重新部署导致出现问题,只需将虚拟机的 PermGen 提高到较大值即可。由于这个问题,我们不久前尝试过 JRockit,它也遇到了同样的重新部署耗尽问题。我们又回到了 SUn JVM。

改变JVM并不是万能的。您可能会遇到新的意外问题(例如看 一篇文章 关于在 4 个不同的 JVM 下启动应用程序)。

  • 你可能会出现类泄漏(例如通过类加载器),这通常发生在重新部署时。坦率地说,我从未见过在 Tomcat 上进行热重新部署(希望有一天能看到)。
  • 您的 JVM 参数可能不正确(例如对于 Sun JDK 6 64 位 -XX:+UseParNewGC 开关会导致内存 PermGen 段泄漏。如果添加额外的开关:-XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled 情况将得到解决。有趣的是,但我从未遇到过上述 Sun JDK 6 32 位的泄漏)。 关联 参阅文章“调整生产部署的 JVM 垃圾收集”。
  • 您的 PermGen 块可能不足以加载类和相关信息(实际上,最常发生在 Tomcat 下重新部署后,旧类保留在内存中,新类正在加载)

根据我过去的经验,调试这种泄漏是我经历过的最棘手的调试之一。

[更新]

有用的文章 如何消除应用程序重新部署上的类加载器链接。

我使用 JRockit,如果我不增加(通过 -XX:MaxPermSize)内存,我仍然会收到 PermGen 错误。我也无法采取任何措施来避免这种情况(除了增加它)。

Perm gen 可能是最简单的内存处理,我怀疑各种虚拟机实现之间会有很大差异。

确保所有在生产中标记为关闭的 Tomcat 配置都在生产中关闭。

是的,一些框架确实会动态生成大量类,但它们应该会自行清理,并且无论如何,您可以在 128Mb 中容纳多个类。

说真的,如果永久代持续上升,那么这就是一个泄漏,应该修复,尽管这可能不是你需要修复的问题。

IBM JVM 没有(2009 年也没有)永久元。您可以阅读有关其的更多信息 分代并发垃圾收集器 这是 Java 7 的默认 GC。

我有时会在 IBM JVM 上运行 Eclipse IDE,因为使用我最喜欢的插件,它经常会填满 HotSpot JVM 的 permgen。当然,可能存在内存泄漏,应该有人修复,但同时我的 IDE 没有崩溃,而且我也没有忙于尝试不同的设置。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top