Java JVM标志CMSClassUnloadingEnabled实际上做什么?
我一生都找不到Java VM标志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虚拟机在世界上的标准外观是:类永远存在。所以一旦加载,即使没
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反射和代理时非常有用。根据forcmsclasssUnloadingEnabled
,要产生任何影响,还必须设置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年。。。我现在从事其他项目。