Describe how the Java garbage collector uses finalization to allow objects to clean up after themselves.
Java Garbage Collection and Finalization
Java's Garbage Collector (GC) is responsible for automatically managing memory by identifying and reclaiming objects that are no longer reachable. It runs in the background, periodically freeing up heap space to prevent memory leaks and optimize performance. Hereâs how it works:
1. Identifying Unreachable Objects
Java uses reachability analysis to determine which objects are no longer in use. It starts from GC roots, which include:
Active thread stacks (local variables, method parameters)
Static fields in loaded classes
JNI (Native Code) references
Objects referenced by active objects
Objects not accessible via any reference chain from GC roots are considered garbage and can be collected.
2. Garbage Collection Algorithms
Different GC algorithms operate to manage memory efficiently:
A. Generational Garbage Collection
Java's heap is divided into three generations:
Young Generation (contains Eden and Survivor spaces)
New objects are allocated in the Eden space.
When full, a Minor GC moves surviving objects to Survivor spaces.
Objects that survive multiple cycles are promoted to Old Generation.
Old Generation (Tenured Generation)
Contains long-lived objects.
When full, a Major GC (Full GC) occurs, which is more expensive.
Permanent/Metaspace (for Class Metadata)
Stores class definitions, interned strings, etc.
JDK 8+ replaced PermGen with Metaspace, which is managed differently.
B. Garbage Collection Techniques
Mark-and-Sweep
Mark phase: Finds and marks reachable objects.
Sweep phase: Deletes unmarked objects and reclaims space.
Copying (Used in Young Generation)
Copies live objects to a new region and discards everything else.
Compact and Sweep (Used in Old Generation)
After sweeping, compacts memory to reduce fragmentation.
3. Common Java Garbage Collectors
Java provides several GC implementations optimized for different workloads:
Serial GC
Uses a single thread.
Best for small applications with low memory needs.
Perform concurrent garbage collection with minimal pause times.
4. Triggering GC Manually (Not Recommended)
The GC can be requested manually using:
System.gc(); // Suggests GC, but JVM may ignore it
Runtime.getRuntime().gc(); // Another way to suggest GC
However, GC runs automatically, and manual invocation should be avoided unless necessary.
5. Monitoring and Tuning GC Performance
For profiling and tuning, Java provides tools like:
GC logs (can be enabled with JVM options like -Xlog:gc)
Conclusion
Java's Garbage Collector plays a crucial role in managing memory efficiently. By using generational collection, different GC algorithms, and automatic memory management, Java ensures that applications run smoothly while minimizing memory leaks.
The garbage collector invokes an object's finalize() method to allow the object to perform any completion processing, such as closing an open socket or disposing of a window, before the object is destroyed.
When an object's finalize() method is invoked, it is possible for the object to become reachable again by assigning itself to a reachable program variable. Because of this possibility, the garbage collector does not immediately destroy an object after its finalize() method has completed. Instead, it waits until the next time that it has identified the object as unreachable.
Timeline for objects during Garbage Collection:
Finalization: Once an object's finalized() method is invoked, the object can clean up after itself, and potentially become reachable again.
Java Virtual Machine
Question: Which option is true about compiling and running the following code?
public class Test extends SuperTest {
String s="abc";
public static void main(String[] args) {
Test t=new Test(); //2
t.finalize(); //3
}
}
Please select one option:
Code will compile only if line 1 is removed.
Code will compile only if line 3 is removed.
Prints "SuperTest".
Prints "SuperTest" only if garbage collector runs.
Causes an exception to be thrown at runtime.
None of the above.
Answer: a Explanation:
Here the code will compile only if line 1 is removed. The super.finalize() method call invokes the finalize() method defined in the Object class. The finalize() method in the Object class throws Throwable, and since it is not handled at line 1, the code will not compile. There is no error in line 3. It is valid to invoke the finalize() method directly. If line 1 is removed, the code will compile and print "SuperTest".