Java Memory Management - Complete explanation
This blog will be a very long one, so grab your popcorn!!
This blog might seem like a notes, actually Yes it’s my personal notes. I might change it to explaining in-depth later.
We will be discussing about 4 things:
Heap and Stack in Java
Garbage Collection
Reference Types
Memory Leaks
Heap and Stack
if you are coming from C/C++, what goes into heap and stack will be different from those languages from Java.
Maybe a Quick compare is,
in C/C++, All variables and objects are stored into Stack, unless you use malloc
or new
, then it will store into Heap.
in Java, All variables and primitive values are stored into Stack, But for the objects, only reference is stored into the stack and real object is stored into heap.
Let’s start.
Memory in Java can be split into 5:
Heap Area
Method Area
JVM Stacks
Native Method Stacks
Program Counter (PC) Registers
Heap Area:
Here Java stores its object instances and primitive Arrays (like: String[], int[], etc.)
Objects created with
new
will be stored here. This aligns with the above points as only way to create objects and arrays is usingnew
.Garbage Collection (GC) automatically reclaims memory occupied by objects that are no longer reachable from any thread.
Each Heap is created per JVM.
public class HeapExample {
public static void main(String[] args) {
String nameObject = new String("Name"); // Created in Heap
int[] numbers = new int[]{1, 2, 3, 4}; // Created in Heap
}
}
Method Area:
It stores Class data like: Class variables, Constant Pool, Class structures, Method bytecode, interfaces.
Previously on Java pre-8 versions, It was called PermGen (Permanent Generation), and was not garbage collected at all. And it was part of Heap.
But on Java 8+, it was called MetaSpace now part of Native memory. And it was garbage collected on Class unloaded.
public class MethodAreaExample {
static int counter = 0; // Stored in MetaSpace
public static void greet() {
// Stored in MetaSpace
System.out.println("Hello from Method Area!");
}
// Method bytecode of non-static methods are stored here in MetaSpace
}
JVM Stacks:
This is the Stack part of Java program. Here it stores all the variables declared in LIFO order.
It Stores method execution data, local variables, return addresses, method arguments.
Each thread has its own stack.
Each Method create its own stack frame inside its main stack
public class StackExample {
public static void main(String[] args) {
// main is the first Stack frame
int a = 10;
int b = 20;
// a, b is stored as local variables to the main stack frame
int sum = add(a, b); // On calling add it creates a new stack frame
}
public static int add(int x, int y) {
// x, y will be stored as local variables to the add stack frame
return x + y;
}
}
Native Memory Stacks:
This functions same as JVM Stacks but handles native code.
Its called C Stacks and not written in Java.
public class NativeExample {
public static void main(String[] args) {
System.loadLibrary("nativeLib"); // Load native C/C++ code
nativeMethod();
}
public static native void nativeMethod(); // Native method
}
Program Counter Registers:
Non-native method has a PC that stores the addresses of available JVM instructions
Native method has PC with undefined
Created Per thread
Garbage Collection
Garbage collection will reclaim memory from the Heap when not reachable from the code.
Since checking for unreachable code on all Heap is expensive, the heap is divided into two parts:
Young Generation
Eden (Newly created objects)
Survivor Space (S0 and S1)
Old Generation
This designed based on Generational Hypothesis, as new objects tend to die quickly compared to old objects. So separating them makes it easy to monitor.
We can garbage collect Young Generation often and monitor old generation less frequent.
Minor GC happens in Young Gen and Major GC happens in Old Gen.
It uses Mark and Sweep algorithm to reclaim memory.
Mark & Sweep:
Mark Phase: goes through all GC nodes (Graph like) via DFS (Stack), marks all dead objects.
Sweep Phase:
If its in Young Generation (Minor GC), it remove marked objects, and take everything from Eden and move to S0 initially.
On the next GC cycle, it will do the same, but now it will move everything to S1. This happens alternatively moving from S0 to S1 and vice-versa.
If the age of the objects is long enough it will be promoted to Old generation.
If its Old Gen (Major GC), it removes marked objects, and do the compaction below.
Compaction:
Only Happens in Old Generation part (major GC). This compaction will move everything to left of the heap so it will avoid fragmentation.
Reference Types
This tells the GC how strong the link to Heap objects, so it can decide whether to reclaim or not.
There are 4 types:
Strong reference type
Soft Reference type
Weak reference type
Phantom
Strong reference type
This is the default we use when assigning to variables.
GC will only reclaim if there are no strong reference pointers to the objects.
Soft reference type
Need to use
SoftReference
class to achieve.Only GC will reclaim if there is no heap memory.
Weak reference type
Need to use
WeakReference
class to acheive.GC will not consider this type when checking for reclaiming. If there are no Strong/Soft references to heap objects, it will reclaim making the weak reference returns null.
Phantom Reference Type
You won’t able to access it. It is useful for making objects dead but not yet reclaimed.
The objects will be added to garbage queue
Use case: it is used in classes for wrapper to native resources.
- Eg: image, when native image is GC-ed, you can use this method to check and GC-ed the wrapper instance.
Memory Leaks
Occurs when the purpose of the object is completed, or is no longer needed by the application, but the GC cannot collect it. This happens when useless object is pointed in some other reference.
Like a instance variable that points to some Instance, but that instance is no longer needed.
Like a static variable that points to some Instance.
Non-static inner class has reference to outer class. In the case when outer class is not needed but inner class is reference. Makes the outer class not GC-ed.
Fixes:
Set the variable to null
Remove the reference from the list or array if its no longer needed.
Don’t store instance to a static variable.
Clear objects from HashMap if not used.
Thanks.