An instance is eligible for garbage collection when null is assigned to it. These are choices made by the JVM implementer.
class Animal
{
public static void main(String[] args)
{
Animal lion = new Animal();
System.out.println("Main is completed.");
}
protected void finalize() {
System.out.println("Rest in Peace!");
}
}
During compilation process as an optimization technique the Java compiler can choose to assign null value to an instance, so that it marks that instance can be evicted.
In the above class, lion instance is never uses beyond the instantiation line. So the Java compiler as an optimzation measure can assign lion = null just after the instantiation line. So, even before SOP’s output, the finalizer can print ‘Rest in Peace!’. We cannot prove this deterministically as it depends on the JVM implementation and memory used at runtime.
Being an automatic process, programmers need not initiate the garbage collection process explicitly in the code. System.gc() and Runtime.gc() are hooks to request the JVM to initiate the garbage collection process.
When we are writing a performance benchmark we may call System.gc() in between runs
Just before evicting an instance and reclaiming the memory space, the Java garbage collector invokes the finalize() method of the respective instance so that the instance will get a chance to free up any resources held by it. Though there is a guarantee that the finalize() will be invoked before reclaiming the memory space, there is no order or time specified. The order between multiple instances cannot be predetermined, they can even happen in parallel. Programs should not pre-mediate an order between instances and reclaim resources using the finalize() method.Any uncaught exception thrown during finalize process is ignored silently and the finalization of that instance is cancelled.