Introduction
Garbage Collection (GC) in Java is an automatic memory management mechanism that removes unused objects from the heap to free up memory. Instead of manually allocating and deallocating memory like in C/C++, Java’s JVM handles it automatically.
Why It Matters
- Prevents memory leaks by cleaning unused objects.
- Optimizes heap usage for better performance.
- Eliminates the need for manual memory deallocation, reducing bugs.
When to Use
You don't explicitly "use" GC in Java—it's always running. However, you can optimize your code to work with the GC, tune its behavior, and understand how it impacts performance.
How Garbage Collection Works in Java
Java objects are created on the heap memory. When no live references point to an object, it becomes eligible for garbage collection.
Core Concepts
- Reachability Analysis: GC uses reference chains starting from GC Roots (local variables, static fields, active threads) to find reachable objects.
- Generational Heap:
- Young Generation: Newly created objects; frequent collections.
- Old Generation (Tenured): Long-lived objects.
- Permanent/Metaspace: Class metadata.
Garbage Collector Types
Collector | Use Case | Strength | Weakness |
---|---|---|---|
Serial GC | Single-threaded apps | Low overhead | Pauses entire app |
Parallel GC | Multi-core servers | High throughput | Longer pauses |
G1 GC | Large heaps | Predictable pause times | Complex tuning |
ZGC/Shenandoah | Ultra-low latency | Concurrent GC | Higher CPU usage |
The finalize()
Method
finalize()
is a special method that the GC calls before reclaiming an object's memory.
@Override
protected void finalize() throws Throwable {
System.out.println("Object is being garbage collected");
}
Problems with finalize()
- Unpredictable: No guarantee when or if it will run.
- Performance overhead: Slows GC because finalizable objects are processed separately.
- Deprecated in Java 9: Use
java.lang.ref.Cleaner
ortry-with-resources
instead.
Real-World Analogy
Think of GC as a housekeeping robot in a hotel:
- Guests (objects) occupy rooms (memory).
- When guests check out (references lost), the robot cleans the room.
- Some guests forget belongings (
finalize()
), but waiting for them delays the cleaning process.
Common Mistakes & Anti-Patterns
-
Calling
System.gc()
manually:- Forces GC, causing unnecessary pauses.
- JVM treats it as a suggestion, not a command.
-
Relying on
finalize()
for resource cleanup:- Use
try-with-resources
instead for deterministic cleanup.
- Use
-
Holding unnecessary references:
- Leads to memory leaks; nullify or limit scope.
-
Creating too many short-lived objects:
- Puts pressure on Young Generation; reuse objects where possible.
Performance & Memory Implications
- GC pause times affect latency-sensitive applications (trading systems, real-time games).
- Choosing the right GC (e.g., G1 for large heaps, ZGC for low latency) can drastically improve performance.
Tuning Tips
- Adjust JVM options like
-Xms
,-Xmx
to control heap size. - Use
-XX:+UseG1GC
for balanced pause times. - Monitor GC with tools like JVisualVM, GC logs.
Best Practices
- Prefer short-lived objects for efficiency in Young Generation.
- Use
WeakReference
/SoftReference
for cache-like structures. - Avoid
finalize()
; useCleaner
ortry-with-resources
. - Profile memory usage regularly with tools.
- Tune GC only after profiling—don’t guess.
Java Version Relevance
Version | Change |
---|---|
Java 8 | PermGen removed, Metaspace introduced |
Java 9 | finalize() deprecated |
Java 11+ | ZGC introduced |
Java 12+ | Shenandoah GC added |
Code Example: Forcing GC (Not Recommended)
public class GCDemo {
public static void main(String[] args) {
for (int i = 0; i < 1000000; i++) {
new GCDemo();
}
System.gc(); // Suggest GC
}
@Override
protected void finalize() {
System.out.println("Object cleaned by GC");
}
}
Conclusion & Key Takeaways
- GC automates memory management but requires understanding for performance tuning.
finalize()
is deprecated—useCleaner
or try-with-resources.- Monitor, profile, and tune GC only when needed.
- Choosing the right GC algorithm is critical for large-scale or low-latency apps.
FAQ
-
What triggers garbage collection in Java?
Loss of all references to an object makes it eligible; JVM decides when to run GC. -
Is
System.gc()
guaranteed to run GC?
No, it's only a request. -
What replaced
finalize()
in modern Java?java.lang.ref.Cleaner
andtry-with-resources
. -
Can I disable GC?
No, but you can tune it or use low-level memory management in special JVMs. -
How to detect memory leaks in Java?
Use profilers like JVisualVM, YourKit, or Eclipse MAT. -
Does GC clean static variables?
Only when the class is unloaded. -
What’s the difference between Soft and Weak References?
Soft survives low memory, Weak is collected eagerly. -
Which GC is best for large heaps?
G1, ZGC, or Shenandoah. -
Does
finalize()
always run before exit?
No guarantee; app may terminate before GC. -
How does GC affect performance?
Pause times can affect latency; proper tuning minimizes impact.