2

I'm in a place where repeated deploy-undeploy actions of the same war-file on server (tomcat) is leading to PermGen OutOfMemoryError. My goal is to make sure that I unload all classes when the war is undeployed.

Here is a class I have:

public class ClassA {
//static variables & methods
//instance variables & methods

    private EnumInsideClassA myState = EnumInsideClassA.VALUE1;

    private enum EnumInsideClassA
    {
        VALUE1,
        VALUE2
    }
}

When I cleared all the references of ClassA, I could not see ClassA and it was unloaded when war was un-deployed. However, I still see the enum references and ClassA$EnumInsideClassA is not unloaded.

There is no getter for 'myState' instance variable and it just going to be used with ClassA

Any help is appreciated

Chris
  • 5,584
  • 9
  • 40
  • 58
  • Have you tried the JVM args _"-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled"_? This is a similar question: [link](http://stackoverflow.com/questions/88235/how-to-deal-with-java-lang-outofmemoryerror-permgen-space-error) – samlewis Apr 08 '12 at 08:27
  • Thank you for the response. Yes I tried it some time back. And I tried it again now. However, inner class (Enum) is not being cleaned up. One this more is that ClassA is still unloaded with out these JVM options as well. – Chris Apr 08 '12 at 08:59

2 Answers2

1

However, I still see the enum references and ClassA$EnumInsideClassA is not unloaded.

If you can see the enum references, you should be able to see where they are. Now there will be some enum references accessible via a hidden static field of the enum class, but these should be circular references and shouldn't cause the enum to remain reachable. See if there are enum references somewhere else.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • I see the references in a Vector inside the ClassLoader. I do not see it any class with in my heirarchy. – Chris Apr 08 '12 at 09:44
  • References to the `enum` values? How can that be? Why would the classloader need to know about the `enum` values? – Stephen C Apr 08 '12 at 10:24
  • Well.. as I understand, there will be one object created per each enum's type and all the objects using this type of enum point to it. Correct me if I'm wrong but enum will also be complied as a type of class (meaning it will have a separate .class file). The classloader loading the enum will have its definition & object of it – Chris Apr 08 '12 at 10:38
  • @Chris - but `enum` is not materially different to any other class in this respect. Any reachable reference to the classloader, or to any class loaded by the classloader, or any instance of any of those classes will result in a permgen leak when you undeploy / redeploy. – Stephen C Apr 09 '12 at 03:13
1

The problem seems to be that enum instances are not unloaded by the classloader. I have a test servlet project and all it has is an enum. It doesn't have to be private or inner-class enum either, but it does need to be referenced at least once so that the instances are created. It seems to be true that the jvm doesn't treat the enum as anything special. I see the same problem with static instances (ie static instances of custom classes do not get garbage collected on classloader unload).

I've tried the various -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled with no success. This might be JVM specific (I'm on Mac OS X, and they don't seem to have those options, but -Xincgc didn't work either: http://developer.apple.com/library/mac/#documentation/Java/Reference/Java_VMOptionsRef/Articles/JavaVirtualMachineOptions.html). There's a lot of info on stackoverflow, eg Dealing with "java.lang.OutOfMemoryError: PermGen space" error

Probably the best fix to this specific issue (servlet re-deploy) is to have all your enums in a jar that doesn't need to be unloaded.

FIY: my environment is Mac OS X 10.6.8, Java 1.6.0_31

Community
  • 1
  • 1
Jacob Mouka
  • 2,005
  • 18
  • 26