PermGen与电梯和docker的问题

我正在开发标准的升降平台(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。 我认为我认为永久的一代记忆是用于类和string的东西是正确的? 我记得有点与.NET内存模型混淆了…

为什么会发生这种情况? 默认值是疯狂的低? 它是否与所有的Scala必须为函数对象和类似的FP事物创build的辅助对象? 每次我用新编写的代码(每隔几分钟)就重新启动Jetty,我想它会重新加载类。但是即使如此,它不能成为那么多吗? JVM不能够处理大量的类吗?

干杯

从这个职位 :

出现这种例外的原因很简单:
permgenspace是Java VM中存储的类属性,比如方法,字段,注释和静态variables等,但是这个空间具有不被垃圾收集器清理的特殊性。 所以如果你的web应用程序使用或创build了很多类(我正在考虑几代dynamic类),那么你很可能遇到了这个问题。 这里有一些解决scheme,帮助我摆脱了这个例外:

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

可能是这可能有所帮助。

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

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

JVM 1.6.0_27说:请使用:

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

查看完整的热点JVM选项 – mroe 的完整参考 。

如果在运行mvn jetty:run时看到这个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

你也可以把这些永久的放在你的环境中。

这是因为你所build议的重新加载类。 如果你正在使用大量的库,那么类的总和将会在每次重启时迅速增长。 尝试使用VisualVM监控您的jetty实例,以获得重新加载时内存消耗的概述。

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

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

根据您的部署,烫发设置可能很低。 某些应用程序和/或容器组合确实包含一些内存泄漏,所以当某个应用程序被取消部署时,有时类似于类加载器的东西不会被收集,导致填充Perm空间,从而产生错误。

不幸的是,目前在这种情况下最好的select是通过下面的jvm标志来最大化perm空间(例如192m perm大小):

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

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