What does JVM flag CMSClassUnloadingEnabled actually do?

103,500

Solution 1

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

For 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.

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.

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

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

Solution 2

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 ClassUnloading that is true by default which (presumably) affects the other garbage collectors.

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.

Setting CMSClassUnloadingEnabled might help 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.


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.

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

Solution 3

An example where this is useful:

Setting -XX:+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled on 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.

It wasn't trivial to trace. The following code always returned the same proxy class for 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 n was incremented at every call. When adding the flags, n was still incremented, but at least those temporary classes were removed from memory.

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

Share:
103,500

Related videos on Youtube

adrian
Author by

adrian

Updated on September 04, 2020

Comments

  • adrian
    adrian over 3 years

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

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

    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.

  • Smilediver
    Smilediver over 11 years
    According to stackoverflow.com/a/3720052/2541 for CMSClassUnloadingEnabled to have any impact, UseConcMarkSweepGC must also be set
  • nurettin
    nurettin about 11 years
    +1 for sharing real experience. We also had this problem on torquebox where the server generated a huge number of classes due to JRuby compilation processes.
  • nurettin
    nurettin about 11 years
    also note that -XX:+CMSPermGenSweepingEnabled is deprecated in favor of -XX:+CMSClassUnloadingEnabled
  • Bill Rosmus
    Bill Rosmus almost 11 years
    Not sure how this affects the idea of using UseConcatSweepGC, but it appears there was a bug recently fixed in CMSClassUnloadingEnabled. It is remarked as fixed here: bugs.sun.com/bugdatabase/view_bug.do?bug_id=8000325
  • Kevin Meredith
    Kevin Meredith over 10 years
    For languages like Groovy that dynamically define classes, is it good practice to enable this flag to periodically clean out PermGen?
  • Aaron Digulla
    Aaron Digulla over 10 years
    @Kevin: Yes, definitely. See at the bottom of groovy.codehaus.org/Running: "Groovy creates classes dynamically, but the default Java VM does not GC the PermGen. If you are using Java 6 or later, add -XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC. UseConcMarkSweepGC is needed to enable CMSClassUnloadingEnabled."
  • rustyx
    rustyx almost 10 years
    A real fix for this issue though is to create the port once and re-use it. That's how JAX-WS is supposed to be used. The port is also 100% thread safe.
  • Lukas Eder
    Lukas Eder almost 10 years
    @rustyx: Can you back that claim with some authoritative link? I've always been very wary of re-using web services proxies and stubs... E.g. see Apache CXF disclaimers. Or this question
  • David Roussel
    David Roussel over 9 years
    @BillR any idea how to interpret that bug report? In what version was CMSClassUnloadingEnabled set to default to true? I couldn't work it out.
  • Victor
    Victor over 9 years
    A good article about using UseConcMarkSweepGC and CMSClassUnloadingEnabled together. blog.redfin.com/devblog/2012/06/…
  • Bill Rosmus
    Bill Rosmus over 9 years
    @DavidRoussel looking at it my assumption would be that would be fixed now.
  • Artem
    Artem over 7 years
    @Lukas Eder It's just a curious, you said: "Weblogic created a new proxy class for every web service call", does it mean if I make simple get/post request, Weblogic creates a new Proxy instance (maybe it's in the past at this moment). Does my insight correct?
  • Lukas Eder
    Lukas Eder over 7 years
    @rukavitsya: As I've said in my answer. Every time I called the above logic, a new proxy was created
  • Artem
    Artem over 7 years
    @Lukas Eder Does it reproduce at this time?
  • Lukas Eder
    Lukas Eder over 7 years
    @rukavitsya: Hey, I'm sorry, I have no clue. That was in 2012... I work on other projects now.
  • mt.uulu
    mt.uulu over 6 years
    no longer valid for 1.8: blogs.oracle.com/poonam/…