Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Possible Memory leak in Number of Loaded classes in Java Application

Tags:

java

profiling

I recently began profiling an osgi java application that I am writing using VisualVM. One thing I have noticed is that when the application starts sending data to a client (over JMS), the number of loaded classes starts increasing at a steady rate. The Heap size and the PermGen size remains constant, however. The number of classes never falls, even after it stops sending data. Is this a memory leak? I think it is, because the loaded classes have to be stored somewhere, however the heap and permgen never increase even after I run the application for several hours.

For the screenshot of my profiling application go here

like image 903
Kyle Avatar asked Oct 03 '08 16:10

Kyle


3 Answers

Are you dynamically creating new classes on the fly somehow?

Thanks for your help. I figured out what the problem is. In one of my classes, I was using Jaxb to create an XML string. In doing this, JAXB ueses reflection to create a new class.

JAXBContext context = JAXBContext.newInstance(this.getClass());

So although the JAXBContext wasn't saying around in the heap, the classes had been loaded.

I have run my program again, and I see a normal plateau as I would expect.

like image 167
Kyle Avatar answered Oct 06 '22 07:10

Kyle


I'm willing to bet that your problem is related to bytecode generation.

Many libraries use CGLib, BCEL, Javasist or Janino to generate bytecode for new classes at runtime and then load them from controlled classloader. The only way to release these classes is to release all references to the classloader.

Since the classloader is held by each class, this also means that you should not release the references to all classes as well [1]. You can catch these with a decent profiler (I use Yourkit - search for multiple classloader instances with the same retained size)

One catch is that the JVM does not unload classes by default (the reason is backwards compatibility - that people assume (wrongly) that static initializers would be executed only once. The truth is that they get executed every time a class is loaded.) To enable unloading, you should pass some use the following options:

-XX:+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled

(tested with JDK 1.5)

Even then, excessive bytecode generation is not a good idea, so I suggest you look in your code to find the culprit and cache the generated classes. Frequent offenders are scripting languages, dynamic proxies (including the ones generated by application servers) or huge Hibernate model (in this case you can just increase your permgen).

See also:

  1. http://blogs.oracle.com/watt/resource/jvm-options-list.html
  2. http://blogs.oracle.com/jonthecollector/entry/presenting_the_permanent_generation
  3. http://forums.sun.com/thread.jspa?messageID=2833028
like image 39
BNL Avatar answered Oct 06 '22 07:10

BNL


You might find some hotspot flags to be of use in understanding this behavior like:

  • -XX:+TraceClassLoading
  • -XX:+TraceClassUnloading

This is a good reference:

http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp

like image 36
Alex Miller Avatar answered Oct 06 '22 07:10

Alex Miller