"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 found
时PermGen OutOfMemoryError
是什么原因?
是否有可能 OutOfMemoryError
的原因是在重新部署期间处理应用程序请求?
我特别低 PermGen
在应用程序重新部署期间强制 PermGen 中的 GC,因为 PermGen
仅在内存压力下清理 - 我决定监视 OutOfMemoryError 是否仍然影响我的应用程序。
有几件事值得一看。
- 您是否有足够的 PermGen 来同时容纳至少 2 个应用程序实例?我相信有时垃圾收集器需要多次传递才能删除所有引用,因此需要一些 "margin" 为 GC 释放一个实例并加载另一个实例。
- 尝试切换到另一个垃圾收集器。我见过我只能用 GC 和 Parallell 中的错误来解释的情况,CMS 和 G1 在这些情况下的行为不同。
- 如果您想尝试另一种方法来查找 GC 根路径,您可以查看 this blog series of mine or Arit。
- 您可能还想通过将我的 ClassLoader Leak Prevention Library 添加到您的应用程序来查看问题是否得到解决。如果是,请查看日志以了解潜在原因。
我在 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 found
时PermGen OutOfMemoryError
是什么原因?
是否有可能 OutOfMemoryError
的原因是在重新部署期间处理应用程序请求?
我特别低 PermGen
在应用程序重新部署期间强制 PermGen 中的 GC,因为 PermGen
仅在内存压力下清理 - 我决定监视 OutOfMemoryError 是否仍然影响我的应用程序。
有几件事值得一看。
- 您是否有足够的 PermGen 来同时容纳至少 2 个应用程序实例?我相信有时垃圾收集器需要多次传递才能删除所有引用,因此需要一些 "margin" 为 GC 释放一个实例并加载另一个实例。
- 尝试切换到另一个垃圾收集器。我见过我只能用 GC 和 Parallell 中的错误来解释的情况,CMS 和 G1 在这些情况下的行为不同。
- 如果您想尝试另一种方法来查找 GC 根路径,您可以查看 this blog series of mine or Arit。
- 您可能还想通过将我的 ClassLoader Leak Prevention Library 添加到您的应用程序来查看问题是否得到解决。如果是,请查看日志以了解潜在原因。