JVM 标志 CMSClassUnloadingEnabled 实际上做了什么?

2022-08-31 06:33:22

我无法找到Java VM标志实际作用的定义,除了一些非常模糊的高级定义,例如“摆脱您的PermGen问题”(顺便说一句,它没有)。CMSClassUnloadingEnabled

我看过Sun's/Oracle的网站,甚至选项列表实际上也没有说明它的作用。

根据标志的名称,我猜CMS垃圾回收器默认情况下不会卸载类,并且此标志将其打开 - 但我不能确定。


答案 1

更新这个答案与Java 5-7相关,Java 8修复了这个问题:https://blogs.oracle.com/poonam/about-g1-garbage-collector,-permanent-generation-and-metaspace Kudos转到mt.uulu

对于 Java 5-7:

Oracle/Sun VM 对世界的标准看法是:类是永恒的。因此,一旦加载,即使没有人再关心,它们也会保留在内存中。这通常没有问题,因为您没有那么多纯粹的“设置”类(=用于设置一次,然后再也不会使用)。因此,即使他们占用1MB,谁在乎呢。

但最近,我们有像Groovy这样的语言,它们在运行时定义类。每次运行脚本时,都会创建一个(或多个)新类,并且它们会永远保留在PermGen中。如果您正在运行服务器,则意味着您有内存泄漏。

如果启用 GC,则 GC 也会扫描 PermGen,并删除不再使用的类。CMSClassUnloadingEnabled

[编辑]您还必须启用(感谢Sam Hasler)。看到这个答案:https://stackoverflow.com/a/3720052/2541UseConcMarkSweepGC


答案 2

根据博客文章 Java JVM 的最完整的 -XX 选项列表,它确定是否在 CMS 垃圾回收器下启用了类卸载。缺省值为 。默认情况下,还有另一个调用的选项,它(可能)会影响其他垃圾回收器。falseClassUnloadingtrue

这个想法是,如果GC检测到以前加载的类不再在JVM中的任何位置使用,它可以回收用于保存类字节码和/或本机代码的内存。

如果您当前正在使用 CMS 收集器,则设置 CMSClassUnloadingEnabled 可能有助于解决您的 permgen 问题。但是,您很可能没有使用CMS,或者您有一个真正的类装入器相关的内存泄漏。在后一种情况下,您的类永远不会在GC中显示为未使用...因此永远不会被卸载。


Aaron Digulla说“上课是永远的”。严格来说,这并不是真的,即使在纯粹的Java世界中也是如此。实际上,类的生存期与其类装入器相关联。因此,如果您可以安排类装入器被垃圾回收(这并不总是一件容易的事),那么它加载的类也将被垃圾回收。

实际上,这是在对 Web 应用进行热重新部署时发生的情况。(或者至少,如果你能避免导致permgen存储泄漏的问题,这就是应该发生的事情。


推荐