【问题标题】:Reason for PermGen OutOfMemoryError when "No GC root found"?“未找到 GC 根”时出现 PermGen OutOfMemoryError 的原因?
【发布时间】:2015-12-26 20:37:07
【问题描述】:

我在 webapp 中修复了 3 个不同的PermGenOutOfMemoryError 问题,并且它在受限-XX:MaxPermSize=66m 中的任意数量的重新部署(我不尝试大于 30)仍然存在。运行应用程序需要大约 55 MB 的 PermGen

修复内存泄漏的主要原因是练习并让开发环境更愉快 - 使用<Context reloadable="true"> 编译后我的 webapp 在 3 秒后重新部署!

刚才我发现catalina.out有错误:

Dec 26, 2015 5:28:09 PM org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor run
SEVERE: Unexpected death of background thread ContainerBackgroundProcessor[StandardEngine[Catalina]]
java.lang.OutOfMemoryError: PermGen space

Exception in thread "ContainerBackgroundProcessor[StandardEngine[Catalina]]" 
Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "ContainerBackgroundProcessor[StandardEngine[Catalina]]"

像往常一样,我运行 visualvm 并运行 OQL:

select unique(map(heap.objects('java.lang.ClassLoader'), 'classof(it)'))

并查看org.apache.catalina.loader.WebappClassLoader 实例。我实际所做的可以用 OQL 来描述:

filter(heap.objects('org.apache.catalina.loader.WebappClassLoader'),
                    'it.state.name.toString() == "DESTROYED"')

那个实例没有释放PermGen 内存。但是当我调用find最近的GC root时,我得到No GC root found

No GC root foundPermGen OutOfMemoryError是什么原因?

OutOfMemoryError 的原因是否可能是在重新部署期间处理应用程序请求?

我特别低PermGen 在应用程序重新部署期间强制 PermGen 中的 GC,因为 PermGen 仅在内存压力下清理 - 我决定监控 OutOfMemoryError 是否仍然影响我的应用程序。

【问题讨论】:

    标签: java out-of-memory permgen


    【解决方案1】:

    有几件事值得一看。

    1. 您是否有足够的 PermGen 来同时保存至少 2 个应用程序实例?我相信有时垃圾收集器需要多次传递才能删除所有引用,因此需要为一个实例为 GC 释放和另一个实例被加载有一些“余量”。
    2. 尝试切换到另一个垃圾收集器。我见过我只能用 GC 中的错误来解释的情况,而 Parallell、CMS 和 G1 在这些情况下的行为不同。
    3. 如果您想尝试另一种查找 GC 根路径的方法,可以查看 this blog series of mineArit
    4. 您可能还想通过将我的ClassLoader Leak Prevention Library 添加到您的应用程序来查看问题是否得到解决。如果是这样,请查看日志以了解潜在原因。

    【讨论】:

    • 感谢支持!我相信我属于案例1。我已经考虑过将PermGen 的大小设为应用要求的两倍。对你的描述感到惊讶,GC 可能由于多通道机制而失败......
    • 一年前我已经阅读了你关于 GC 的所有博客系列,与classloader-leak-prevention 一起玩的任务在我的 TODO 列表中。但是直到现在我还没有能力去寻找泄漏,所以应该重新阅读你的博客))
    • 我听说 Parallel GC 与 PermGen 存在问题,并被认为已被现代硬件弃用。所以我总是使用-XX:+UseConcMarkSweepGC(等待G1 被普遍接受)。
    猜你喜欢
    • 1970-01-01
    • 2013-06-10
    • 2013-03-08
    • 1970-01-01
    • 2016-05-03
    • 2014-07-15
    • 2011-08-03
    • 2017-04-20
    • 2014-05-31
    相关资源
    最近更新 更多