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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3334911/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 22:22:05  来源:igfitidea点击:

What does JVM flag CMSClassUnloadingEnabled actually do?

javajvmclassloaderjvm-arguments

提问by Rich

I cannot for the life of me find a definition of what the Java VM flag CMSClassUnloadingEnabledactually does, other than some very fuzzy high-level definitions such as "gets rid of your PermGen problems" (which it doesn't, btw).

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

I have looked on Sun's/Oracle's site, and even the options listdoesn't actually say what it does.

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

Based upon the name of the flag, I'm guessing that the CMS Garbage Collector doesn't by default unload classes, and this flag turns it on - but I can't be sure.

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

采纳答案by Aaron Digulla

UpdateThis answer is relevant for Java 5-7, Java 8 has this fixed: https://blogs.oracle.com/poonam/about-g1-garbage-collector,-permanent-generation-and-metaspaceKudos go to mt.uulu

更新此答案与 Java 5-7 相关,Java 8 已修复此问题:https://blogs.oracle.com/poonam/about-g1-garbage-collector,-permanent-generation-and-metaspace Kudos go to mt.乌鲁

For Java 5-7:

对于 Java 5-7:

The standard Oracle/Sun VM look on the world is: Classes are forever. So once loaded, they stay in memory even if no one cares anymore. This usually is no problem since you don't have that many purely "setup" classes (= used once for setup and then never again). So even if they take up 1MB, who cares.

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

But lately, we have languages like Groovy, that define classes at runtime. Every time you run a script, one (or more) new classes are created and they stay in PermGen forever. If you're running a server, that means you have a memory leak.

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

If you enable CMSClassUnloadingEnabledthe GC will sweep PermGen, too, and remove classes which are no longer used.

如果启用CMSClassUnloadingEnabledGC 也将清除 PermGen,并删除不再使用的类。

[EDIT]You will also have to enable UseConcMarkSweepGC(thanks to Sam Hasler). See this answer: https://stackoverflow.com/a/3720052/2541

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

回答by Stephen C

According to the blog post The most complete list of -XX options for Java JVM, it determines if class unloading is enabled under the CMS garbage collector. The default is false. There is another option called ClassUnloadingthat is trueby default which (presumably) affects the other garbage collectors.

根据博客文章Java JVM 的 -XX 选项的最完整列表,它确定是否在 CMS 垃圾收集器下启用了类卸载。默认值为false. 有一个叫另一种选择ClassUnloadingtrue在默认情况下它(大概)影响其他垃圾收集器。

The idea is that if the GC detects that a previously loaded class is no longer used anywhere in the JVM, it can reclaim the memory used to hold the classes bytecode and/or native code.

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

Setting CMSClassUnloadingEnabled mighthelp with your permgen problem if you are currently using the CMS collector. But the chances are that you are not using the CMS, or that you have a genuine classloader related memory leak. In the latter case, your class will never appear to the GC to be unused ... and will therefore never be unloaded.

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



Aaron Digulla says "classes are for ever". This is not strictly true, even in the purely Java world. In fact, the lifetime of a class is tied to its classloader. So if you can arrange that a classloader is garbage collected (and that is not always an easy thing to do) the classes that it loaded will also be garbage collected.

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

In fact, this is what happens when you do a hot redeploy of a webapp. (Or at least, that's what should happen, if you can avoid the problems that lead to a permgen storage leak.)

事实上,这就是当您对 web 应用程序进行热重新部署时会发生的情况。(或者至少,这是应该发生的,如果你能避免导致永久存储泄漏的问题。)

回答by Lukas Eder

An example where this is useful:

一个有用的例子:

Setting -XX:+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabledon our Weblogic 10.3 JVM helped resolving a problem where the JAX-WS implementation created a new proxy class for every web service call, eventually leading to out of memory errors.

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

It wasn't trivial to trace. The following code always returned the same proxy class for port

追踪并非易事。以下代码始终返回相同的代理类port

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);

Internally, this proxy delegated to an instance of weblogic.wsee.jaxws.spi.ClientInstance, which again delegated to a new $Proxy[nnnn]class where nwas incremented at every call. When adding the flags, nwas still incremented, but at least those temporary classes were removed from memory.

在内部,此代理委托给 的一个实例weblogic.wsee.jaxws.spi.ClientInstance,该实例再次委托给一个新$Proxy[nnnn]类,该类n在每次调用时都会增加。添加标志时,n仍然增加,但至少那些临时类已从内存中删除。

On a more general note, this can be very useful when making heavy use of Java reflection and proxies through java.lang.reflect.Proxy

更一般地说,这在大量使用 Java 反射和代理时非常有用java.lang.reflect.Proxy