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.
‘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.
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
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.
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.
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
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.
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.
Bulletproof Java Code: A Practical Strategy for Developing Functional, Reliable, and Secure Java Code
Use Java? If you do, you know that Java software can be used to drive application logic of Web services or Web applications. Perhaps you use it for desktop applications? Or, embedded devices? Whatever your use of Java code, functional errors are the enemy!
To combat this enemy, your team might already perform functional testing. Even so, you're taking significant risks if you have not yet implemented a comprehensive team-wide quality management strategy. Such a strategy alleviates reliability, security, and performance problems to ensure that your code is free of functionality errors.Read this article to learn about this simple four-step strategy that is proven to make Java code more reliable, more secure, and easier to maintain.