One of the least
understood areas by Java Developers is garbage collection. Java Developers feel
JVM takes care of garbage collection and they need not worry about memory
allocation, deallocation etc. But as the applications grows complex, so does
the garbage collection and once it is complex, the performance do get a hit. So
it will benefit the Java Developers to understand how garbage collection works
and how to fix the 'Out of Memory' issues in java. There are 2 quite common
'Out of Memory' issues. The 1st one is 'Heap Size' and the 2nd one is 'PermGen
Space'.
Permanent Generation and ClassLoaders.
Java objects are instantiations of the Java classes. Every time a new java object is created, JVM creates an internal representation of that object and stores it in the heap. If the class is accessed for the first time, then it has to be loaded by the JVM. Class loading is the process of locating the corresponding class file, seeking the file on the disk, loading the file and parsing the structure. It is the ClassLoaders responsibility to ensure proper loading of the classes.Each and every class in the java program needs to be loaded by the same ClassLoader. ClassLoaders are the instances of java.lang.ClassLoader class. For now, ClassLoader loads the java classes in Perm Space.
JVM
also creates an internal representation of the java classes and those are
stored in the permanent generation. During garbage collection, both java
objects and classes are viewed as objects and are garbage collected in the same
way. Initially both the java objects and classes are stored in the heap space.As a performance optimization the permanent generation
was created and classes were put into it.Classes are part of our JVM
implementation and we should not fill up the Java heap with our data
structures. Permanent Generation is allocated outside the heap size. The permanent Generation contains the following class information:
- Methods of a class.
- Names of the classes.
- Constants pool information.
- Object arrays and type arrays associated with a class.
- Internal objects used by JVM.
- Information used for optimization by the compilers.
Now that we understood what Permanent Generation is, let us see what causes the memory issue in this region.
PermGen Space
'Java.Lang.OutOfMemoryError: PermGen Space' occurs when JVM needs to load the definition of a new class and there is no enough space in PermGen.
The default PermGen Space allocated is 64 MB for server mode and 32 MB for client mode.
There could be 2 reasons why PermGen Space issue occurs.
The 1st
reason could be your application or your server has too many classes and the
existing PermGen Space is not able to accommodate all the classes.
-XX:MaxPermSize=XXXM
If the issue is due to insufficient PermGen
Space due to large number of classes, then you can increase the PermGen space
by adding the --XX:MaxPermSize=XXm parameter. This will increase the space
available for storing the classes and should
-XX:MaxPermSize=256m
-XX:+CMSClassUnloadingEnabled
This parameter indicates whether class unloading enabled when using CMS
GC. By default this is set to false and so to enable this you need explicitly
set the following option in java options.
-XX:+CMSClassUnloadingEnabled
If you enable CMSClassUnloadingEnabled the GC will sweep PermGen, too,
and remove classes which are no longer used.This option will work only when UseConcMarkSweepGC is also enabled using the
below option.
-XX:+UseConcMarkSweepGC
-XX:+CMSPermGenSweepingEnabled
This parameter indicates whether sweeping of perm gen is enabled.
By default this parameter is disabled and so will need to explicitly set this
for fine tuning the PermGen issues.
This option is removed in Java 6 and so you will need to use -XX:+CMSClassUnloadingEnabled
if you are using Java 6 or above.
So the options added to resolve the PermGen Space memory issues will
look like
-XX:MaxPermSize=128m -XX:+UseConcMarkSweepGC XX:+CMSClassUnloadingEnabled
Memory leaks
And the 2nd reason could be memory leak. How the class definitions that
are loaded could can become unused.
Normally in Java, classes are forever. So once the classes are loaded,
they stay in memory even if that application is stopped on the server. Dynamic
class generation libraries like cglib use lot of PermGen Space since they
create a lot of classes dynamically. Heavy use of Proxy classes, which are
created synthetically during runtime. It's easy to create new Proxy classes when
a single class definition could be reused for multiple instances.
Spring and
Hibernate often makes proxies of certain classes. Such proxy classes are loaded
by a classloader. The generated class definitions are never discarded causing
the permanent heap space to fill up fast.
For PermGen
space issues, you will need identify the cause of leak and fix it. Increasing
the PermGen space will not help, it will only delay the issue, since at some
point the PermGen space will still be filled up.
If you are
using Tomcat and are haunted by memory leaks, the latest versions of Tomcat
have capability to fix the some of the memory leak issues.
Conclusion
Once you come across the PermGen Space issue, you will need to find out if the issue is due to large number of classes your application is loading or due to memory leak. If it is due to large number of classes, you can fine tune to increase the PermGen Space allocated and that will resolve the issue. If the issue is due to memory leak, you will need to find the root cause of the leak and address it. Certain frame works like cglib, Spring, Hibernate creates large number of dynamically generated classes, so it is better to allocate more PermGen Space for projects using these frameworks.
Venkata Kiran, great article!
ReplyDeleteBut those wno doesn't use Tomcat and still experiencing classloader memory leaks (or any other memory leaks) could try Plumbr (plumbr.eu)!
It finds memory leaks very fast and gives the exact line of code where the leak is created for me to fix it.