Memory in Java is largely made easy by garbage collection. This automatic management of memory does not prevent from any memory problem. Here are some basics elements I find useful to review while facing a memory error.
The memory is divided in two distinct spaces, even if this might change in Java 8.
- The PermGen space contains classes definitions
- The Heap space contains objects
When a memory problem occurs, an error is raised. This throwable contains information about the cause of the problem and the impacted memory space. Most of time, these informations are sufficient to help solve the problem.
The JVM options mentioned in this post are for HotSpot (Sun/Oracle implementation). For more informations, the official HotSpot tuning documentation is very helpful.
The space allocated for classes definitions is full. This can happen if the environment loads a large number of classes (common in Java EE environments). The allocated space can be configured via the JVM option -XX:PermSize=256m (for 256 megabytes).
In some situations, this saturation can be caused by a hot deployment. A workaround for such a problem is the JVM option -XX:+CMSClassUnloadingEnabled. This clear all references to obsolete classes definitions. A very helpful option when processing multiple hot deployments in a Tomcat environment.
A blog post by Frank Kieviet explains a pattern that could also cause PermGen space errors.
The created objects stay in the Heap space while being referenced in the executed program. When an object is not referenced any more, it becomes available for release by the Garbage Collector (GC). Most of time, the GC acts when the available memory becomes low. This is highly configurable with many JVM options.
If there is no memory leak, the easy solution is to increase the available space.
All becomes complicated when there is a memory leak. The cause can be difficult to identify. Several tools help to identify the problem nature.
I personally generate an hprof file. This is done using JVM option -XX:+HeapDumpOnOutOfMemoryError. Another JVM option -XX:HeapDumpPath=... allows to specify the generated file location. The Eclipse MAT tools helps to visualize the generated file.
Another solution is to run your program with the Eclipse TPTP tools. But I prefer to avoid this option because it requires much resources to run (and was quite unstable the last time I used it).
This error happens when the system spends too much time executing garbage collection. Literally, there is no memory saturation but the system uses most of its memory despite garbage collections. A simple workaround can be to extend the Heap space. If the problem persists, tuning the GC configuration will probably be the solution. A hint can be the -XX:-UseParallelGC JVM option (some documentation is available here).