java.lang.OutOfMemoryError: PermGen 空间

Posted

技术标签:

【中文标题】java.lang.OutOfMemoryError: PermGen 空间【英文标题】:java.lang.OutOfMemoryError: PermGen space 【发布时间】:2011-11-15 07:07:27 【问题描述】:

问题: 我正在为我的 spring 应用程序使用 eclipse-helios 和 Tomcat 6 并获取

java.lang.OutOfMemoryError: PermGen space  

每当我调试我的应用程序时

我试过了

    添加

    -vmargs -Dosgi.requiredJavaVersion=1.5 -Xms512m -Xmx1024m -XX:MaxPermSize=1204m -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled 给eclipse.ini

    tomcat_home/bin中创建setenv.shsetenv.bat,内容如下

    设置 JAVA_OPTS="-Xms256m -Xmx512m -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled"

    在 Eclipse 中手动运行垃圾收集器。我通过

    启用了这个选项

    Window -> Preferences -> General -> 并选择始终在后台运行并显示堆状态

    重启 Tomcat 一百次。

    重新启动 eclipse,有时当挫折超出限制时重新启动我的机器..

最好的部分是我仍然得到错误。 有什么我应该尝试的解决方案吗?


我尝试运行其他应用程序,但仍然出现同样的错误,恕我直言,我的应用程序太小而不会导致错误,我的应用程序在我的同事设置中运行良好。

【问题讨论】:

我知道这是许多问题的完全重复 - 我建议你然后对你想回答的问题给予奖励,或者改写这个问题(提供具体细节等),因此它不是完全重复。 @Hyangelo:PermGen 用完不是简单的内存泄漏的结果。 您混淆了 JVM 配置参数。 eclipse JVM(eclipse crash)还是Tomcat JVM实例出现问题?如果是后者,选项 #1 和 #3 不应有任何影响,因为它们与 eclipse IDE JVM 实例相关。 How to deal with "java.lang.OutOfMemoryError: PermGen space" error 的可能重复项 - 因为您没有按照那里的答案建议做所有事情。具体来说,增加 tomcat 中的 permgen 大小 @arnaud:我知道这是一个愚蠢的问题,我真的是个愚蠢的人,知道后才提出这个问题。我尝试了我在网上找到的任何东西,因为我不够专业,无法检测到愚蠢的错误。将尝试更新我的知识。谢谢。 【参考方案1】:

您的前 3 个选项针对 2 个不同的 JVM。选项 #1 和 #3 修改 eclipse JVM 实例,这是管理您的 IDE 的 JVM。选项 #2 修改 Tomcat JVM 实例。这就是为什么在启动 eclipse 和 Tomcat(假设它们是唯一运行的 Java 应用程序)时,您会在任务管理器中看到两个 java.exe 文件(在 windows 的情况下)。

了解 Eclipse WTP(在我的情况下为 Indigo)提供的 Tomcat 插件调用外部(依赖于操作系统的)脚本来启动/停止 Tomcat 很重要。相反,它们直接通过命令行 (java.exe ...) 生成 Tomcat JVM。如果要修改从 eclipse 中启动的 Tomcat 实例的 JVM 参数,则需要修改相应的Run Configuration。尝试在那里修改 JVM 参数,它应该可以工作(见屏幕截图)。

【讨论】:

@Ajinkya:没问题,我在一年前左右打过那场战争 :-) 所以它确实奏效了?【参考方案2】:

试试set JAVA_OPTS=-XX:NewSize=128m -XX:MaxNewSize=256m -XX:PermSize=128m -XX:MaxPermSize=256m -XX:+DisableExplicitGC -Xms512m -Xmx1536m

永久代是特殊的,因为它持有 描述用户类的元数据(不属于 Java 语言)。此类元数据的示例是描述 类和方法,它们存储在永久代中。 具有大型代码库的应用程序可以快速填满这部分 将导致 java.lang.OutOfMemoryError: PermGen no 的堆 不管你的 -Xmx 有多高,机器上有多少内存。

【讨论】:

我应该删除我在问题中提到的 -vmargs 吗? 我将它用于 JBoss AS,并将其添加到启动脚本(Windows 上的 .bat 和 linux 上的 .sh)。它应该是你的 JVM 启动的一个参数,所以最容易在 tomcat 启动脚本中将它添加到 JAVA_OPTS 中。 Perm gen space isnt cleared by the Garbage Collector - 这是不正确的,仅适用于默认配置中的 CMS 收集器。 我的立场是正确的,只是在这里阅读一下 blogs.oracle.com/jonthecollector/entry/… 并将其从我的帖子中删除【参考方案3】:

您使用哪些工具来分析正在运行的应用程序?我推荐使用 eclipse mat,尽管 jdk 可以使用 jconsole 和 visualvm。 您是否在应用程序中加载了很多类,在循环的某个地方? 字符串呢?字符串池的大小是多少? 很抱歉,重启tomcat、eclipse或机器并不能解决问题;您将需要分析和分析您的应用程序以解决问题。进行堆转储(您可以使用 jmap)并进行分析。

【讨论】:

【参考方案4】:

我会在 JAVA_OPTS 变量中添加 -XX:PermSize=1024m,因为错误可能来自 Tomcat。 我对 eclipse.ini 文件不熟悉。

【讨论】:

【参考方案5】:

我不知道eclipse.ini 的详细信息,但我认为这只是在启动 Eclipse 时设置标志。不影响运行/调试应用程序。就个人而言,每当我想在运行/调试应用程序时更改设置时,我只需在相应的运行/调试配置中添加 JVM 标志。

此外,如果您使用超过 1 giga 的 perm 空间,我猜代码中有问题。 尝试定位perm空间消耗的来源并修复它。我并不是说这很容易,但为了使应用程序正常工作,它是必需的。 ...除非真的打算使用 1 giga perm 空间,但我对此有些怀疑。

您可以查找例如string.intern()。如果您在每个请求/条目/任何字符串上执行此操作,您将无用地填充您的 perm 空间,因为它将永久保留字符串的副本。

【讨论】:

感谢您的建议。我将堆和 permgen 大小保持为 512。你的“eclipse 配置和你的 tomcat 配置不匹配”到底是什么意思? 您的 tomcat JAVA_OPTS 的最小/最大堆、永久大小和 GC 策略的值与您的 eclipse.ini 配置不同。 @Ajinkya:您是否尝试将 -XX:MaxPermSize=512m 放入应用程序的运行/调试配置中? (播放/调试图标右侧的小箭头 -> 菜单末尾 -> 参数选项卡 -> VM 参数) 我的新价值观set JAVA_OPTS=-XX:NewSize=512m -XX:MaxNewSize=1024m -XX:PermSize=128m -XX:MaxPermSize=512m -XX:+DisableExplicitGC -Xms512m -Xmx1024m-vmargs -Dosgi.requiredJavaVersion=1.5 -Xms512m -Xmx1024m -XX:MaxPermSize=512m 感谢您的建议也将尝试。【参考方案6】:

对我来说 -Xmx1024m -XX:MaxPermSize=256m 成功了。

【讨论】:

以上是关于java.lang.OutOfMemoryError: PermGen 空间的主要内容,如果未能解决你的问题,请参考以下文章