为啥我只会看到 jmap -permstat 中的“死”类加载器(引导程序除外)?
Posted
技术标签:
【中文标题】为啥我只会看到 jmap -permstat 中的“死”类加载器(引导程序除外)?【英文标题】:Why would I see only "dead" classloaders from jmap -permstat (except the bootstrap)?为什么我只会看到 jmap -permstat 中的“死”类加载器(引导程序除外)? 【发布时间】:2011-07-11 21:24:52 【问题描述】:我们一直在将应用程序中的 permgen 内存空间推得越来越高,我正试图找出我们是否有某种泄漏进入 permgen 区域。我们不执行热取消部署/重新部署操作,但我们有大量代理,包括动态代理和 CGLIB 生成的代理。我们还做了一些复杂的类加载器位来支持各种用例,我怀疑这些也可能导致 permgen 浪费。
所以我在我们正在运行的应用程序上运行 jmap -permstat,希望能够深入了解哪些可能会填满我们的 permgen 空间。 (我还运行了一个包含活动对象和死对象的普通堆转储,以便我可以追踪可能来自 permstat 输出的线索)。
但是,在 jmap permstat 列出的 2400 个类加载器中,除了引导类加载器之外的所有类加载器都被列为“死”。这没有任何意义,因为该应用程序肯定是实时的,并且正在运行。
我的理解是,如果一个类加载器符合垃圾回收条件,jmap 会将其报告为“已死”,但我在这里肯定是错的......
我错过了什么?这里的“死”是什么意思?除了我在这里可能存在的误解之外,谷歌搜索并没有提供很多答案。
【问题讨论】:
这个博客条目可能很有趣:drorbr.blogspot.com/2008/11/… Dead 意味着它应该准备好被 GC 处理(但显然它们不是)。因此,与您的泄漏有更多可能的相关性。否则,我在 Helios 的 Eclipse-Days 上看到了一个简洁的工具,即 MAT。 eclipse.org/mat 用于调查内存泄漏的强大工具。也许这有帮助。最好的问候,丹尼尔 Leschkowski 请发布您的 VM 版本和 java 参数 java 版本 "1.6.0_21" Java(TM) SE Runtime Environment (build 1.6.0_21-b06) Java HotSpot(TM) 64-Bit Server VM (build 17.0-b16, mixed mode) 我知道这可能无济于事,但我会升级到 1.6.0_26。当然,欢迎您在尝试升级之前查看他们的release notes,但如果您的复制案例运行速度很快,那就去做吧。另外,调用java
时传递了哪些VM 参数?
我也在我的jmap -permstat
中看到了这一点。有时 -permstat 在计算“活跃度”时会出现异常。在那种情况下,我猜它只是找不到类加载器的路径。但也许是死者?标志不是基于“可卸载”,而是基于“类加载器本身可访问”。不知道。我只能建议使用 heapdump(和 MAT)来查找泄漏。
【参考方案1】:
这里有一些想法:
-
升级到最新的虚拟机。
如果出于某种原因您使用
-XX:+UseConcMarkSweepGC
运行,那么请确保您也使用-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled
在 jhat 中执行“来自 Rootset 的引用链”,以查看谁持有该实例。
记得排除弱引用!
This long post 有点复杂,我自己也没试过,也许对你有帮助。
尝试另一个 VM,例如JRockit
【讨论】:
以上是关于为啥我只会看到 jmap -permstat 中的“死”类加载器(引导程序除外)?的主要内容,如果未能解决你的问题,请参考以下文章
Knockout JS 订阅 2 个 observables 的方式是,如果 2 个 observables 中的任何一个发生变化,我只会收到一次通知