为啥我只会看到 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 中的“死”类加载器(引导程序除外)?的主要内容,如果未能解决你的问题,请参考以下文章

执行 jmap -heap 选项时 JVM 是不是停止?

Knockout JS 订阅 2 个 observables 的方式是,如果 2 个 observables 中的任何一个发生变化,我只会收到一次通知

Kubernetes 应用java程序无法使用jmap,jstack的解决方案

为啥这个 SVG 中的渐变显示为黑色?

为啥初始化列表允许 C++ 中的类型缩小?

LARAVEL:当有多个项目时,我只会从我的桌子上拿一个项目。我将如何获得所有这些并输出它们?