哪种免费 JVM 实现具有最好的 PermGen 处理能力?
题
我在 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 空间。
其他提示
从技术上讲,“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 中容纳多个类。
说真的,如果永久代持续上升,那么这就是一个泄漏,应该修复,尽管这可能不是你需要修复的问题。