41

我正在标准 Lift 平台(maven 和 jetty)上开发。我反复(每两天一次)得到这个:

Exception in thread "7048009@qtp-3179125-12" java.lang.OutOfMemoryError: PermGen space
2009-09-15 19:41:38.629::WARN:  handle failed
java.lang.OutOfMemoryError: PermGen space

这是在我的开发环境中。这不是问题,因为我可以继续重新启动服务器。在部署中我没有这些问题,所以这不是一个真正的问题。我只是好奇。

我对JVM不太了解。我认为我认为永久代内存用于类和实习字符串之类的东西是正确的?我记得有点与 .NET 内存模型混淆了......

为什么会发生这种情况?默认值是不是非常低?它是否与 Scala 必须为 Function 对象和类似的 FP 事物创建的所有辅助对象有关?每次我用新编写的代码(每隔几分钟)重新启动 Jetty 时,我想它会重新加载类等。但即便如此,它不可能有那么多可以吗?而且JVM不应该能够处理大量的类吗?

干杯

4

5 回答 5

44

这篇文章

发生此异常的原因很简单: Java VM
permgenspace存储类属性(如方法、字段、注释以及静态变量等)的位置,但该空间具有不被垃圾收集器清理的特殊性. 因此,如果您的 web 应用程序使用或创建了很多类(我正在考虑动态生成类),那么您很可能会遇到这个问题。以下是一些帮助我摆脱此异常的解决方案:

  • -XX:+CMSClassUnloadingEnabled:此设置启用 permgenspace 中的垃圾收集
  • -XX:+CMSPermGenSweepingEnabled:允许垃圾收集器从内存中删除偶数类
  • -XX:PermSize=64M -XX:MaxPermSize=128M: 增加分配给 permgenspace 的内存量

可能这会有所帮助。

2012 年 7 月编辑(将近 3 年后):

Ondra Žižka评论(我已经更新了上面的答案):

JVM 1.6.0_27 说:请使用:

  • CMSClassUnloadingEnabled(使用 CMS GC 时是否启用类卸载)
  • 代替CMSPermGenSweepingEnabled将来

请参阅完整的Hotspot JVM 选项 - mroe 的完整参考。

于 2009-09-20T18:29:12.023 回答
12

如果你在运行时看到这个 mvn jetty:run,设置MAVEN_OPTS.

对于 Linux:

export MAVEN_OPTS="-XX:+CMSClassUnloadingEnabled -XX:PermSize=256M -XX:MaxPermSize=512M"
mvn jetty:run

对于 Windows:

set "MAVEN_OPTS=-XX:+CMSClassUnloadingEnabled -XX:PermSize=256M -XX:MaxPermSize=512M"
mvn jetty:run

现在应该好了。如果没有,增加-XX:MaxPermSize.

您也可以将它们永久地放到您的环境中。

于 2012-07-23T01:53:54.547 回答
3

这是因为按照您的建议重新加载了类。如果您使用大量库等,则每次重新启动时类的总和都会迅速增长。尝试使用 VisualVM 监控您的码头实例,以了解重新加载时的内存消耗情况。

于 2010-09-22T17:30:28.077 回答
2

邮件列表 ( http://groups.google.com/group/liftweb/ ) 是 Lift 的官方支持论坛,您可以在此获得更好的答案。我不知道您的开发设置的详细信息(您不会详细介绍),但我假设您在 Jetty 中重新加载您的战争而没有实际重新启动它。Lift 不执行动态类生成(如上面 VonC 所建议的),但 Scala 将每个闭包编译为一个单独的类。如果您在几天的时间里向代码添加和删除闭包,则可能有太多的类被加载而从未被卸载并占用了 perm 空间。我建议您启用上面 VonC 提到的选项 JVM 选项,看看它们是否有帮助。

于 2009-09-20T19:06:30.407 回答
1

永久代是 JVM 放置可能不会像自定义类加载器那样被(垃圾)收集的东西的地方。

根据您部署的内容,perm gen 设置可能很低。某些应用程序和/或容器组合确实包含一些内存泄漏,因此当应用程序被取消部署时,有时不会收集类加载器之类的东西,导致填充 Perm Space 从而产生您遇到的错误。

不幸的是,目前在这种情况下最好的选择是使用以下 jvm 标志来最大化 perm 空间(例如 192m perm 大小):

-XX:MaxPermSize=192M (or 256M)

另一种选择是确保容器或框架不会泄漏内存。

于 2009-09-20T18:28:16.817 回答