GC Eligibility
What Makes an Object Eligible for GC
An object becomes eligible for garbage collection when it is no longer reachable from any live thread or static reference.
public class GCEligibility {
public static void main(String[] args) {
// Object eligible immediately after line below
createObject();
// Object with no references - eligible
String temp = new String("temporary");
temp = null; // now eligible for GC
// Array with no references
int[] data = new int[1000];
data = null; // eligible
// Objects in disconnected graph
Node a = new Node();
Node b = new Node();
a.next = b;
b.next = a; // circular reference - still eligible!
a = null; // entire cycle becomes eligible
b = null; // nothing points to them
}
static void createObject() {
Object obj = new Object();
// obj is eligible after method returns
}
}
Common scenarios:
- Reference set to null
- Object goes out of scope
- Circular references with no external root
- Weak references (SoftReference, WeakReference, PhantomReference)
GC Roots
GC Roots
GC roots are the starting points for garbage collection. Objects reachable from roots are alive; everything else is garbage.
Types of GC Roots:
- Local variables - in stack frames of active methods
- Static variables - referenced by classes
- JNI references - native method references
- Monitors - synchronized blocks
- Class loaders - loaded classes
public class GCRoots {
// Static variable - GC root
static Object staticObj = new Object();
// Instance variable (not a root itself, but reachable from staticObj)
Object instanceObj;
public void method() {
// Local variable - GC root
Object localVar = new Object();
instanceObj = localVar; // connects instance to root
}
}
Reference reachability:
- Strong > Soft > Weak > Phantom
- Strong: prevent GC
- Soft: prevent GC until memory pressure (caches)
- Weak: eligible immediately (WeakHashMap)
- Phantom: enqueued after finalize (cleanup)
GC Algorithms
GC Algorithms Overview
1. Serial GC
- Single-threaded
- Stop-the-world pauses
- Good for single-core apps
-XX:+UseSerialGC
2. Parallel GC
- Multi-threaded
- Stop-the-world pauses
- Default in Java 8
-XX:+UseParallelGC
3. G1GC (Garbage First)
- Region-based
- Predictable pause times
- Default in Java 9+
-XX:+UseG1GC
4. ZGC
- Ultra-low latency
- Pause times < 1ms
-XX:+UseZGC
// No code changes needed - just JVM flags
// java -XX:+UseG1GC -Xmx4g MyApp
Generational Collection:
- Young Generation: Eden + Survivor (where new objects go)
- Old Generation: Long-lived objects
- Minor GC: Cleans young gen (fast)
- Major GC: Cleans old gen (slower)
System.gc()
System.gc() - Advisory Only
System.gc() is a hint to the JVM to run garbage collection, not a command. The JVM may ignore it.
public class SystemGCDemo {
public static void main(String[] args) {
// Create many objects
for (int i = 0; i < 1000000; i++) {
new Object();
}
// Suggest GC (not guaranteed)
System.gc();
// Force finalization (deprecated)
System.runFinalization(); // Don't use this
}
}
Why it's unreliable:
- JVM decides when to run GC
- May do nothing if memory is sufficient
- May run a full GC even without your request
- Performance impact if called unnecessarily
Best practice: Never rely on System.gc(). Let the JVM manage GC automatically.
Finalize() and Deprecation
finalize() - Why It's Deprecated
Object.finalize() was meant for cleanup but is deprecated since Java 9.
public class FinalizeDemo {
@Override
protected void finalize() throws Throwable {
try {
// Cleanup resources
System.out.println("Finalizing: " + this);
} finally {
super.finalize();
}
}
}
Problems with finalize():
- Unpredictable timing - may never run
- Performance overhead - slows GC
- Thread-safety issues - runs in finalizer thread
- Can resurrect objects - defeats GC purpose
- No guarantees of execution order
Modern alternatives:
try-with-resourcesfor AutoCloseableCleanerclass (Java 9+)- Explicit
close()methods
// Modern approach
public class Resource implements AutoCloseable {
@Override
public void close() {
// Cleanup resources here
System.out.println("Resource closed");
}
}
try (Resource r = new Resource()) {
// Use resource
} // close() called automatically
Key takeaway: Never use finalize(). Use try-with-resources or Cleaner instead.
GC Best Practices
GC Best Practices
1. Minimize object creation in loops
// Bad - creates new String each iteration
for (int i = 0; i < 10000; i++) {
String s = new String("prefix" + i);
}
// Better - reuse StringBuilder
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {
sb.setLength(0); // clear
sb.append("prefix").append(i);
String s = sb.toString(); // still creates, but less garbage
}
2. Use appropriate data structures
// Bad for large datasets - all in memory
List<HugeObject> all = loadAllFromDB();
// Better - stream/process lazily
try (Stream<HugeObject> stream = loadFromDB()) {
stream.filter(x -> x.isValid())
.map(x -> x.transform())
.forEach(x -> process(x));
}
3. Avoid memory leaks
// Bad - static collection grows forever
static List<Object> cache = new ArrayList<>();
// Better - use WeakHashMap or bounded cache
static WeakHashMap<Key, Value> cache = new WeakHashMap<>();
4. Size collections appropriately
// Bad - may resize multiple times
List<Item> items = new ArrayList<>();
for (int i = 0; i < 100000; i++) items.add(new Item());
// Better - pre-size
List<Item> items = new ArrayList<>(100000);
for (int i = 0; i < 100000; i++) items.add(new Item());
5. Monitor GC logs
# Enable GC logging
java -Xlog:gc*:file=gc.log MyApp
Practice Problems
For each variable, determine if the referenced object is eligible for GC at the marked point: ```java String a = "hello"; String b = a; a = null; String c = b; // MARK HERE b = null; // MARK HERE ```
Solution
**First MARK:** `a = null; b = c = "hello"` → String "hello" is NOT eligible (reachable via b and c)
**Second MARK:** `b = null; c = "hello"` → String "hello" is still NOT eligible (reachable via c). But `b`'s reference is null. The string "hello" is a string pool literal, so it's a GC root anyway.Quiz
1. When is an object eligible for garbage collection?
2. What is a GC root?
3. Why is Object.finalize() deprecated?
4. What is the primary purpose of Garbage Collection in Java?
Flashcards
Question
What are the four types of references in Java?
Click to reveal answer
Answer
Strong (prevent GC), Soft (prevent until memory pressure), Weak (eligible immediately), Phantom (enqueued after finalize).
Question
What is the difference between Minor GC and Major GC?
Click to reveal answer
Answer
Minor GC cleans the Young Generation (fast). Major GC cleans the Old Generation (slower). Full GC cleans entire heap.
Question
What replaced finalize() in Java 9+?
Click to reveal answer
Answer
java.lang.ref.Cleaner class and AutoCloseable with try-with-resources pattern.
Question
What is Garbage Collection in Java?
Click to reveal answer
Answer
Garbage Collection in Java is a key concept in Java programming.
Question
When to use Garbage Collection in Java?
Click to reveal answer
Answer
Use Garbage Collection in Java when building production systems that require reliability, scalability, and maintainability.
Revision Notes
Key Takeaways
- 1.GC eligibility = no reachable references from GC roots
- 2.System.gc() is advisory, not a command
- 3.finalize() is deprecated - use try-with-resources
- 4.G1GC is the default since Java 9
Interview Tips
- •Explain that circular references with no roots are still collected
- •Mention the four reference types (strong, soft, weak, phantom)
- •Never say System.gc() forces collection - it's a hint
- •Explain why finalize() is unreliable (timing, resurrection, thread safety)
Cheat Sheet
GC Cheat Sheet
Eligibility
- No strong/soft references
- Unreachable from GC roots
GC Roots
- Local vars (active stack)
- Static vars
- JNI references
- Monitors
Algorithms
- Serial: single-thread, small apps
- Parallel: multi-thread, default Java 8
- G1: region-based, default Java 9+
- ZGC: ultra-low latency
Best Practices
- Minimize object creation in loops
- Use try-with-resources
- Pre-size collections
- Use WeakHashMap for caches