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

Java JVM标志CMSClassUnloadingEnabled实际上做什么?,java,jvm,classloader,jvm-arguments,Java,Jvm,Classloader,Jvm Arguments,我一生都找不到Java VM标志cmsclasssUnloadingEnabled实际作用的定义,除了一些非常模糊的高级定义,如“摆脱永久性问题”(,顺便说一句) 我看过Sun/Oracle的网站,甚至没有说它到底做了什么 根据该标志的名称,我猜CMS垃圾收集器默认情况下不会卸载类,并且该标志会将其打开-但我不能确定。更新这个答案与Java 5-7相关,Java 8有一个固定的问题:值得称赞 对于Java 5-7: Oracle/Sun虚拟机在世界上的标准外观是:类永远存在。所以一旦加载,即使没

我一生都找不到Java VM标志
cmsclasssUnloadingEnabled
实际作用的定义,除了一些非常模糊的高级定义,如“摆脱永久性问题”(,顺便说一句)

我看过Sun/Oracle的网站,甚至没有说它到底做了什么


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

更新这个答案与Java 5-7相关,Java 8有一个固定的问题:值得称赞

对于Java 5-7:

Oracle/Sun虚拟机在世界上的标准外观是:类永远存在。所以一旦加载,即使没有人再关心,它们也会留在记忆中。这通常是没有问题的,因为您没有那么多纯粹的“设置”类(=一次用于设置,然后再也不会使用)。所以即使它们占用1MB,谁在乎呢

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

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


[编辑]您还必须启用
useConMarkSweepGC
(感谢)。看到这个答案:

根据博客文章,它确定是否在CMS垃圾收集器下启用了类卸载。默认值为
false
。还有另一个名为
类卸载
的选项,默认情况下是
true
,它(可能)会影响其他垃圾收集器

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

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


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


事实上,当你重新部署一个webapp时,就会发生这种情况。(或者,如果可以避免导致永久性存储泄漏的问题,至少应该这样做。)

这是一个有用的示例:

在Weblogic 10.3 JVM上设置
-XX:+CMSClassUnloadingEnabled-XX:+CMSClassUnloadingEnabled
,有助于解决JAX-WS实现为每个web服务调用创建新代理类的问题,最终导致内存不足错误

追踪并不是一件小事。以下代码始终为
端口返回相同的代理类

final MyPortType port = 
Service.create(
        getClass().getResource("/path/to.wsdl"), 
        new QName("http://www.example.com", "MyService"))
    .getPort(
        new QName("http://www.example.com", "MyPortType"), 
        MyPortType.class);
在内部,该代理委托给
weblogic.wsee.jaxws.spi.ClientInstance
的一个实例,该实例再次委托给一个新的
$proxy[nnnn]
类,其中
n
在每次调用时递增。添加标志时,
n
仍然递增,但至少这些临时类已从内存中删除


更一般地说,这在通过

大量使用Java反射和代理时非常有用。根据for
cmsclasssUnloadingEnabled
,要产生任何影响,还必须设置
UseConcMarkSweepGC
,不确定这对使用UseConcatSweepGC的想法有何影响,但似乎最近在CMSClassUnloadingEnabled中修复了一个bug。这里的评论是固定的:@凯文:是的,当然。请参阅下面的:“Groovy动态创建类,但默认Java VM不会GC PermGen。如果您使用的是Java 6或更高版本,请添加
-XX:+cmsclasssUnloadingEnabled-XX:+UseConcMarkSweepGC
UseConcMarkSweepGC
,以启用
cmsclasssUnloadingEnabled
”一篇关于同时使用UseConMarkSweepGC和CMSClassUnloadingEnabled的好文章。不再适用于1.8:+1分享真实经验。我们在torquebox上也遇到了这个问题,因为JRuby编译过程导致服务器生成了大量的类。还请注意,
-XX:+cmsPermGensWeapingEnabled
被弃用,取而代之的是
-XX:+CMSClassUnloadingEnabled
这个问题的真正解决方法是创建一次端口并重新使用它。这就是JAX-WS的使用方式。端口也是100%线程安全的。@rukavitsya:正如我在回答中所说的。每次我调用上述逻辑时,都会生成一个新的代理created@rukavitsya:嘿,对不起,我不知道。那是在2012年。。。我现在从事其他项目。