代码之家  ›  专栏  ›  技术社区  ›  Joe

电梯和码头的永久性问题

  •  41
  • Joe  · 技术社区  · 15 年前

    我正在开发标准的升降平台(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为函数对象和类似的fp对象创建的所有辅助对象有关吗?每次我用新编写的代码重新启动Jetty(每隔几分钟),我都会想象它会重新加载类等,但即便如此,它也不能有那么多的代码?JVM不应该能够处理大量的类吗?

    干杯

    5 回复  |  直到 11 年前
        1
  •  44
  •   Community omersem    7 年前

    this post :

    发生此异常的原因很简单:
    这个 permgenspace 是将类属性(如方法、字段、注释和静态变量等)存储在Java VM中,但此空间具有不被垃圾收集器清理的特殊性。 所以,如果你的webapp使用或创建了很多类(我认为是动态的一代类),你很可能会遇到这个问题。 以下是一些帮助我摆脱此异常的解决方案:

    • -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 Options - The complete reference 为了MROE。

        2
  •  12
  •   Ondra Žižka David Lilljegren    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 .

    您也可以将这些永久地放到您的环境中。

        3
  •  3
  •   col    14 年前

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

        4
  •  2
  •   Jorge Ortiz    15 年前

    邮件列表( http://groups.google.com/group/liftweb/ )是电梯的官方支持论坛,在那里你可以得到更好的答案。我不知道你的开发设置的细节(你不太详细),但我假设你在码头重新加载你的战争,而实际上没有重新启动它。Lift不执行动态类生成(正如上面vonc所建议的那样),但scala将每个闭包编译为单独的类。如果您在几天内添加和删除代码的闭包,可能会加载太多的类,而从不卸载,并占用perm空间。我建议您启用上面vonc提到的选项jvm选项,看看它们是否有帮助。

        5
  •  1
  •   fixitagain    13 年前

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

    根据部署的内容,perm gen设置可能较低。某些应用程序和/或容器组合确实包含一些内存泄漏,因此当应用程序未部署时,有时某些内容(如类加载器)不会被收集,从而导致填充perm空间,从而产生错误。

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

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

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