"No GC root found" 时 PermGen OutOfMemoryError 的原因?

Reason for PermGen OutOfMemoryError when "No GC root found"?

我在 webapp 中修复了 3 个不同的 PermGen OutOfMemoryError 问题,并且它在受限 -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 nearest GC root 我得到 No GC root found.

No GC root foundPermGen OutOfMemoryError是什么原因?

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

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

有几件事值得一看。

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