☕️ How Java Handles Memory Management
🔗 1️⃣ Memory Areas in JVM
When you run a Java program, the JVM divides memory into several regions:
| Memory Area | What it Stores | Example |
|---|---|---|
| Method Area (part of Metaspace) | Class metadata (names, methods, static fields, etc.) | public static int count |
| Heap | All objects & instance variables | new String(), new ArrayList() |
| Stack | Local variables & method call data | int x = 10, object references |
| PC Register | Tracks current instruction for each thread | Bytecode instruction being executed |
| Native Method Stack | Tracks native (non-Java) method calls | Native I/O calls |
🔥 2️⃣ Automatic Garbage Collection (GC)
In languages like C/C++, developers must manually allocate and free memory using malloc() and free(). In Java, the JVM does this for you via Garbage Collection (GC).
How does GC work?
- When an object is no longer reachable (no reference pointing to it), it becomes eligible for GC.
- GC runs in the background and reclaims memory by destroying unreachable objects.
- This reduces the risk of memory leaks (but doesn’t eliminate them completely if you hold on to unnecessary references).
📦 3️⃣ Java Memory Model (Heap Division)
The Heap itself is divided into areas for more efficient GC.
| Section | Purpose |
|---|---|
| Young Generation | For new (short-lived) objects |
| Old Generation (Tenured) | For long-lived objects |
| Eden Space | Where new objects are first allocated |
| Survivor Spaces | Objects that survive GC cycles in Eden |
Example
String s = new String("Hello");
slives in the stack (as a reference).- The actual
Stringobject ("Hello") lives in the heap.
⚙️ 4️⃣ Garbage Collection Algorithms
Java has different GC algorithms, like:
| GC Type | When Used | Key Benefit |
|---|---|---|
| Serial GC | Single-threaded apps | Simple, works well for small heaps |
| Parallel GC | Multi-core machines | Uses multiple threads to speed up collection |
| G1 GC (Garbage First) | Large heaps | Focuses on predictable pause times |
| ZGC (Java 11+) | Low-latency apps | Works with very large heaps (up to TB scale) |
🚀 5️⃣ Finalization (rarely used)
If an object has a finalize() method, the GC may call it before destroying the object — but this is slow, unreliable, and generally discouraged. Better alternatives: try-with-resources or explicit cleanup methods.
⚠️ What You Still Need to Watch For
✅ Memory Leaks in Java
- Even though GC exists, you can still have logical memory leaks if you hold unnecessary references. Example:
List<Object> cache = new ArrayList<>();
- If you forget to remove objects from
cache, even if the objects are not needed anymore, they will not be garbage collected.
✅ OutOfMemoryError (OOM)
- Happens when:
- Heap is too small for all objects.
- Too many large objects are held for too long.
- Memory leak exists in your code.
💡 Summary Diagram
JVM Memory
+--------------------+
| Method Area | <- class metadata, static fields
| |
+--------------------+
| Heap | <- objects (new)
| - Young Gen |
| - Old Gen |
+--------------------+
| Stack (per thread) | <- method calls, local vars
+--------------------+
| PC Register | <- current bytecode instruction
+--------------------+
| Native Stack | <- native method calls
+--------------------+
🎯 Quick Recap
| Process | Who Handles It? |
|---|---|
| Object creation | You (with new) |
| Object destruction | JVM (via Garbage Collector) |
| Memory allocation | JVM |
| Memory freeing | JVM |