Java Memory

Why are we talking about Java memory? Isn’t it something java handles internally?

Answer to this is. Yes, Java (JVM) handles its own memory. But its important that we know some basics about java internal memory layout. Read along to understand why.

When a Java process starts, it starts as a single process. It does not share memory with other processes.

A part of OS memory is allotted to the java process (java.exe) – called as the process memory

Java Process memory = Heap Memory + Non Heap Memory

So what is Heap Memory?

The Heap Memory (aka Java heap) stores objects (instances of classes).

Heap memory is the runtime data area from which the Java VM allocates memory for all class instances and arrays. The heap may be of a fixed or variable size. The garbage collector is an automatic memory management system that reclaims heap memory for objects.

This heap memory can be configured through -Xmx and -Xms settings. These are java VM arguments.

-Xms<size>        set initial Java heap size
-Xmx<size>        set maximum Java heap size

If you don’t trust me, run java –help, you should see the java options, one of them will be:

-X            print help on non-standard options

Then do a java -X

Note about VM arguments:
* Options that begin with -X are non-standard (not guaranteed to be supported on all VM implementations), and are subject to change without notice in subsequent releases of the JDK.
* Options that are specified with -XX are not stable and are not recommended for casual use. These options are subject to change without notice.

Source: [http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html]

OK, now coming back to Java heap, its divided into the following parts

Java Heap = Young Generation + Old/Tenured Generation (a good size for YG is 33% of the total heap)

All new objects are created in YG. YG is further divided as follows

Young Generation = Eden Space + Survivor Space.

Eden Space (heap): The pool from which memory is initially allocated for most objects.

Survivor Space (heap): The pool containing objects that have survived the minor garbage collection of the Eden space.
(there are types of GC threads one of them is ‘Minor GC’ which works on Eden space, we’ll not go any deeper into it)

Java uses generational garbage collection. This means that if you have an object foo (which is an instance of some class), the more garbage collection events it survives (if there are still references to it), and the further it gets promoted. It starts in the young generation (which itself is divided into multiple spaces – Eden and Survivor) and would eventually end up in the tenured generation if it survived long enough.

What is Non Heap Memory?

Non Heap Memory = Permanent Space + Code Generation + Socket Buffers + Thread Stacks + Direct Memory Space + JNI Code + Garbage Collection + JNI Allocated memory

The reason I have made Permanent Space bold is that, we will only talk about it and not the other ones.

The permanent generation mainly stores classes which are loaded and string pool ( Strings intern value).

The permanent generation is special because it holds data needed by the virtual machine to describe objects that do not have equivalence at the Java language level. For example objects describing classes and methods are stored in the permanent generation.

You can increase the perm gen size as

-XX:MaxPermSize=256m
(Would set its maximum size to 256m, which is 4 times bigger than the default size.)

— Out Of Memory Error (OOM) —

Its very likely that you have come across

java.lang.OutOfMemoryError: Java heap space
or
java.lang.OutOfMemoryError: PermGen space

1> Java heap space – OOM

When JVM starts, heap space is the initial size of Heap specified by -Xms parameter, as application progresses and objects are created, JVM expands Heap space in Java to accommodate new objects.

JVM also run garbage collector to reclaim memory back from dead objects. JVM expands Heap in Java some where near to Maximum Heap Size specified by -Xmx and if there is no more memory left for creating new object in java heap , JVM throws java.lang.outofmemoryerror and your application dies.

Before throwing OOM Error, JVM tries to run garbage collector to free any available space but even after that not much space available on Heap in Java it results into OutOfMemoryError.

To resolve this error you need to understand your application object profile i.e. what kind of object you are creating, which objects are taking how much memory etc. you can use profiler or heap analyzer to troubleshoot OutOfMemoryError in Java. “java.lang.OutOfMemoryError: Java heap space” error messages denotes that Java heap does not have sufficient space and cannot be expanded further.

Steps to do analysis are:

1> Find the PID of the java process

jps  (if you have started the java process)

or ps -e | grep java [unix]

2> Take heap dump

jmap can be used to for taking the heap dump

jmap -dump:format=b,file=heap.bin 6852   [Note: this will create the dump file from where you run the command and not where the application is running]

or jmap -histo:live 6852 (lets you view the classes in use without creating a dump file)

3> Analyze Heap dump

jhat (java heap analyzer tool) can be used for heap analysis [Note there are other pretty cool tools for this like eclipse MAT, visualVM etc]

C:\Documents and Settings\Joy\Desktop>jhat heap.bin
Reading from heap.bin...
Dump file created Mon Apr 02 16:04:42 IST 2012
Snapshot read, resolving...
Resolving 22822 objects...
Chasing references, expect 4 dots....
Eliminating duplicate references....
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.

The problem is that you will not be able to do steps 1 and 2 OOM is already thrown and the process has died.

So its better to start the java application using the -XX:+HeapDumpOnOutOfMemoryError vm argument.

This takes the heap dump in a file named java_<pid>.hprof

But it could happen that the heap dump is so large that jhat is unable to read it….

C:\Documents and Settings\Joy\Desktop>jhat C:\MagicWrkspce\TestSpring\java_pid4916.hprof
Reading from C:\Wrkspce\TestSpring\java_pid4916.hprof...
Dump file created Mon Apr 02 16:42:10 IST 2012
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Hashtable.put(Hashtable.java:420)
at com.sun.tools.hat.internal.model.Snapshot.addHeapObject(Snapshot.java:153)
at com.sun.tools.hat.internal.parser.HprofReader.readInstance(HprofReader.java:728)
at com.sun.tools.hat.internal.parser.HprofReader.readHeapDump(HprofReader.java:474)
at com.sun.tools.hat.internal.parser.HprofReader.read(HprofReader.java:226)
at com.sun.tools.hat.internal.parser.Reader.readFile(Reader.java:79)
at com.sun.tools.hat.Main.main(Main.java:143)

You’ll then have to increase the heap space for the jhat process..

jhat -J-mx1024m java_pid4916.hprof

You can also use jconsole to monitor your java application.

If its a stand alone application you will need to add this in your vm arguments list

-Dcom.sun.management.jmxremote

You can then start the jconsole by jconsole <PID> command.

2> Perm Gen Space – OOM

java.lang.OutOfMemoryError: PermGen space” error message comes when the permanent generation of Java Heap is full, the application will fail to load a class or to allocate an interned string.

Although this error can occur in normal circumstances, usually, this error is caused by a memory leak.

In short, such a memory leak means that a classloader and its classes cannot be garbage collected after they have been undeployed/discarded.

Typical example is with the use of proxy objects. Spring and Hibernate often make proxies of certain classes. Such proxy classes are loaded by a classloader as well, and often, the generated class definitions – which are loaded like classes and stored in permanent generation heap space – are never discarded, which causes the permanent generation heap space to fill up.

Some third party frameworks, such as cglib(although it might be better for newer versions of the library), appear to be permgen monsters.

So using jdk dynamic proxies instead of cglib might be a good idea when getting the error.

Also, newer versions of Hibernate appear to not use cglib as a bytecode provider anymore, so upgrading your version of Hibernate, might drastically lower your chances on getting the error.

For more reading:
http://www.oracle.com/technetwork/java/gc-tuning-5-138395.html
http://java.sun.com/docs/hotspot/gc1.4.2/faq.html

One response to “Java Memory

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s