在我的最新文章中,我解释了可能导致java.lang.OutOfMemoryError:PermGen空间崩溃的原因 。 现在该讨论该问题的可能解决方案了。 或者,更确切地说,是关于互联网对可能解决方案的建议。 不幸的是,我只能说,我对MythBusters的内心Jamie Hyneman进行了不同的“专家意见”唤醒。
我搜索了有关解决java.lang.OutOfMemoryError:PermGen空间崩溃的方法的当前常识,并浏览了几十个页面,这些页面似乎更适合Google结果。 幸运的是,大多数建议已被提炼为备受推崇的StackOverflow的主题 。 如您所见,该主题非常受欢迎,并获得了一些颇受好评的答案。 但是具有讽刺意味的是,整个主题包含的零解决方案我可以向我推荐。 好吧,除了“查找内存泄漏的原因”外,这当然是绝对正确的,但对回答“如何解决内存泄漏”的问题不是很有帮助。 让我们回顾一下SO页面上提出的建议。
使用-XX:MaxPermSize = XXXM
导致java.lang.OutOfMemoryError的原因有两个:PermGen空间错误。
一种是应用程序服务器和/或应用程序确实确实使用了太多的类,以致它们不适合默认大小的永久代。 绝对有可能,但实际上并非如此。 在这种情况下,增加永久代的大小确实可以节省一天。 如果您唯一的问题是如何在太多的小房子里放太多家具,那就买更大的房子!
但是,如果您的爱心妈妈每周都会给您寄去新家具呢? 您可能无法一遍又一遍地搬到更大的房子。 正如我在上面提到的上一篇文章中所描述的,这正是内存泄漏以及类加载器泄漏的情况。 在此让我清楚:永久代大小的增加不会使您免于类加载器泄漏。 它只能推迟。 并更难预测服务器将淘汰多少次重新部署。
-XX:+ CMSPermGenSweepingEnabled
关于StackOverflow的最流行的答案是将这些选项添加到服务器的命令行中。 而且,他们说:“也可以添加-XX:+ UseConcMarkSweepGC。 只是要确定”。 这些JVM标志的第一个问题是没有关于它们真正作用的解释。 无论是在SO答案中(我都不喜欢告诉您在没有理由的情况下要做某事的答案),还是在整个Internet中都是如此。
确实,除了此页面之外,我找不到有关这些选项的任何文档。 但是,实际上,这甚至没有关系。 绝不会对垃圾收集器选项进行任何修补,以防在班机泄漏时发生。 因为按照定义, 内存泄漏是GC不足的情况。 如果从服务器的类加载器中的某个地方到应用程序的对象或类之间存在有效的实时硬引用,则GC将永远不会将其视为垃圾,也永远不会对其进行回收。 当然,所有这些JVM标志看起来都很聪明和神奇。 在某些情况下,可能确实需要使用它们。 但是它们肯定不够 ,不能解决您的永久代泄漏。
使用JRockit
下一个建议是切换到JRockit JVM。 理由是,由于JRockit没有永久代,因此无法用完它。 当然,这是一个有趣的主张。 不幸的是,它也不能解决我们的问题。
此“解决方案”的唯一结果将是获取java.lang.OutOfMemoryError:Java堆空间,而不是java.lang.OutOfMemoryError:PermGen空间。 在没有单独生成类定义的情况下,JRockit为它们使用通常的Java堆空间。 而且,只要泄漏的根本原因没有得到解决,只要有足够的时间,这些类定义甚至可以填满最大的堆。
重新启动服务器
假装问题已解决的另一种方法是不时重新启动应用程序服务器。 例如,无需重新部署应用程序,只需重新启动整个服务器即可。 但是,当您第一次看到部署了多个应用程序的应用程序服务器时,您会知道在生产环境中几乎不可能做到这一点。 这并不是真正的解决方案。 这是将您的头藏在沙子里的一种方法。
使用Tomcat
实际上,这并不是以前的绝望之作-最近的Tomcat版本确实尝试解决类加载器泄漏。 自己看看他们的文档 。 如果您可以将Tomcat用作目标服务器,并且如果您的泄漏是Tomcat可以成功应对的泄漏之一,那么也许,也许您很幸运,问题就为您解决了。
在此处使用<您最喜欢的探查器工具>
也可能是可行的解决方案。 但是,再加上几个IF 。 首先,您应该能够在受影响的环境中使用该探查器。 正如我之前在其他文章中提到的那样, 探查器施加的开销水平在(生产)环境中可能是不可接受的。 其次,您必须知道如何使用探查器提取所需的信息并确定泄漏的位置。 而我10多年的经验表明,这种情况很少发生。
结论
到目前为止,我们还没有看到java.lang.OutOfMemoryError:PermGen空间错误的任何确定解决方案。 在某些情况下,有些方法是可行的。 但是,令我震惊的是,大多数建议都完全无效 ! 您可能会浪费数天或数周的时间来尝试它们,甚至没有开始解决真正的问题:找到流氓的根本原因,以防泄漏!
幸运的是,从1.1版本开始, Plumbr还发现了PermGen泄漏 。 它告诉您阻止类加载器被释放的根本原因,从而节省了寻找漏洞的时间。 因此,下一次,当遇到java.lang.OutOfMemoryError:PermGen空间消息时, 下载Plumbr并永久摆脱该问题。
参考: Plumbr博客博客上来自我们JCG合作伙伴 Nikita Salnikov Tarnovski的 PermGen神话 。
翻译自: https://www.javacodegeeks.com/2012/12/busting-permgen-myths.html