Garbage collection
Objects created during program execution are automatically removed by a special module of Java Virtual Machine called Garbage Collector.
When an object is not referenced by any threads and when the JVM determines that this object will not be accessed, then it becomes eligible for garbage collection.
Garbage collector then removes those objects from the heap.
java.lang.Object
class has a finalize
method which is automatically called by the garbage collector before it attempts to remove the object from the heap. Starting java 9, finalize
method has been deprecated and a new java.lang.ref.Cleaner
class is added for garbage collection management.
An object of cleaner gets notified automatically when an object becomes eligible for garbage collection or phantom reachable.
A cleaner object has a provision to take some action before the object is garbage collected, same as with finalize()
method.
For this, the object that is being garbage collected needs to be registered with the cleaner object along with the action that should be taken upon garbage collection.
But first, we should understand how a cleaner object is created.
Creating Cleaner
A cleaner object can be created using its static method create as shown below.
Cleaner cleaner = Cleaner.create();
This method creates a new cleaner object and also starts a thread in the background(daemon thread) which keeps on monitoring any objects eligible for garbage collection or the objects which are phantom reachable.
For registering a cleaner to perform an action before garbage collection, you need to invoke
register()
method of a cleaner object. register()
method accepts two arguments
1. An object which the cleaner keeps monitoring for garbage collection. When this object becomes eligible for garbage collection, the cleaner takes the specified action.
2. A java.lang.Runnable
instance which represents the action to be taken.
Code snippet for the above two steps will be
cleaner.register(object, runnableInstance);
where object
is the object which is being monitored for garbage collection and runnableInstance
is an object implementing java.lang.Runnable
.
Needless to say that the cleaning action will be performed in a new java thread.
Remember that the class implementing java.lang.Runnable
should not be a java inner class(either anonymous nor non-anonymous).
This is because an inner class implicitly holds the reference to the outer object, which prevents it from being garbage collected.
Example program
Combining all the discussion, now its time to see it in real action with an example program.
import java.lang.ref.Cleaner; public class CleanerExample { public static void main(String[] args) { // create a cleaner object Cleaner cleaner = Cleaner.create(); // create an object in if-block if(true) { // object that will be garbage collected CleanerExample myObject = new CleanerExample(); // register cleaner cleaner.register(myObject, new State()); } for (int i = 1; i <= 10000; i++) { String[] largeObject = new String[1000]; try { Thread.sleep(1); } catch (InterruptedException e) { } } } private static class State implements Runnable { public void run() { System.out.print("Cleaning action"); } } }
In the above example, the class State
implements java.lang.Runnable
and provides implementation of run
method.
Note that this class is a static nested class.
Object of this class is provided as the action to be taken when the object is garbage collected. When the object is garbage collected, run
method is automatically invoked.
Running this program will print Cleaning action
on the console as output.
- The object that needs to be garbage collected is created inside an
if
-block that will always be executed.
Creating an object inside a block ensures that after the block completes, there are no references to this object left which means that the object now becomes phantom reachable.
You can also use a loop instead of anif
-block. - If the object is created outside the block, then it will not be eligible for garbage collection.
for
loop only serves the purpose of creating additional objects for memory consumption and halting program execution so that the cleaner thread sweeps out the object created insideif
-block.- String array created inside the loop is only for consuming the memory.
If you comment out this line, then the object may never be garbage collected. - Class implementing
java.lang.Runnable
should not be an inner class and the action provided to register method should not be an anonymous implementation ofrun()
. run()
method should not contain any reference to the object which you want to be garbage collected.
Do not forget to hit the clap below.