Memory Analysis of Java Application

Ankita Chaudhari
5 min readApr 19, 2019

--

When we are developing a new module or adding a feature to an existing application we may come across a Memory shortage. So to find out where extra memory is being used is called Memory Analysis. Let’s first learn how memory is allocated by JVM.

The memory on the stack contains method parameters and local variables (to be precise: the references for objects and variables themselves for primitive types). Stack memory is thread-safe as whenever a method is invoked, a stack frame is created where values for parameters and method variables are stored. For every thread, a separate stack frame is created. The stack frame will be cleared when the method is executed. The variables that are references (to objects) are the objects themselves are on the heap and handled by the garbage collector.

So the garbage collection for the stack is not the same as that of the heap, but a stack forms automatic memory management on its own (which predates garbage collection).

Static methods (in fact all methods), as well as static variables, are stored in the PermGen section of the heap, since they are part of the reflection data (class-related data, not instance-related).

Update for clarification:

Note that only the variables and their technical values (primitives or references) are stored in PermGen space.

If you declare a static variable that is referencing an object, then that object itself is stored in the normal sections of the heap (young/old generation of survivor space). Those objects (unless they are internal objects like classes etc.) are not stored in PermGen space.

Garbage collection is performed on heap Space. Heap is not thread-safe. All thread works on the same heap space.

Memory space is divided into two parts:

1] Young generation

2] Old generation

Memory space: Young generation and the old generation

The young generation consists of Eden space and two survivor spaces i.e.

(s0 -> first survivor, s1-> second survivor)

Initially, objects are allocated in Eden space. Once Eden space is full, minor GC occurs. objects are moved to either survivor space(s0 or s1). On further minor/major GC the spaces are swapped for both survivor spaces.

The old generation consists of the Tenured generation. The object which is alive after X number of GCs is moved to the old generation.

There is one more space known as “perm gen/ metaspace”(From java 8 permanent is replaced with meta-space)

Permanent Generation or “Perm Gen” contains the application metadata required by the JVM to describe the classes and methods used in the application. Note that Perm Gen is not part of Java Heap Memory.

Perm Gen is populated by JVM at runtime based on the classes used by the application. Perm Gen also contains Java SE library classes and methods. Perm Gen objects are garbage collected in a full garbage collection.

Minor garbage collection: Young generation GC

Major garbage collection: Old generation GC

Full GC: major GC+ minor GC(Collect old and young generations together) + permanent generation

Now Let’s study tools that provide memory analysis to our application. We need the PID of the application.

Jps shows all the processes running on local and its PID

JSTAT

General command is

jstat -option <pid> <interval> <count>

Abbreviations:

S0 / S1: survivor space

E : Eden space

O: old gen

M: meta space

Ccs : Compressed class space utilization as a percentage.

YGC : young gc

YGCT: young gc time

FGC: Full GC

FGCT: Full GC Time

GCT: Average GC Time

LGCC: Cause of last Garbage Collection.

GCC: Cause of current Garbage Collection.

S0C: denotes the capacity of s0

SOU: denotes memory utilized by s0.

We use this tool to monitor number of gc happening, how frequently it’s happening.

JvisualVM:

JvisualVM is the one that is shipped with java. To invoke these tools, navigate to %JAVA_HOME%/bin in the command prompt. And just type “jvisualvm.exe” and it will open.

There is a plugin provided by Visual GC to see live space occupied by java objects in each space

We can also get live thread dump or heap dump using this tool:

It also shows real-time memory assignments in the “sampler” tab

We can also tune our application, We can control the size of heap memory assigned to the application.

To tune the JVM following parameters are used:

-Xms → To set initial heap size when JVM starts.

-Xmx → for setting the maximum heap size.

-XX:MaxPermGen → For setting maximum size for perm gen.

-XX:MaxMetaspaceSize → For setting maximum size for meta gen(introduced after java 8)

To generate the heap dump we can tune in by using the following JVM parameter:

-XX:+HeapDumpOnOutOfMemoryError

-XX:HeapDumpPath=<Location_For_HeapDump_File>

jcmd <pid> GC.heap_dump <file-path>

After generating the heap dump file we can analyze the heap dump file using MAT(Memory Analyzing tool) provided by the eclipse.

It gives all the information about the possible reason for a memory leak.

Following are the JVM parameters that can be used to collect the info on GC activities:

-Xloggc:asc_gc.log

-XX:+PrintGCDetails

-XX:+PrintGCDateStamps

After getting GC logs we can analyze those on

https://gceasy.io/ site this gives us a clear picture of our overall GC activity.

References:

https://app.pluralsight.com/library/courses/understanding-java-vm-memory-management/table-of-contents

--

--