When we run java application, JVM will starts up and creates a heap area for storing objects. Since heap area is limited, It is required to manage heap area efficiently by removing the unreached objects. The process of removing unreached objects from heap memory is known as Garbage collection.
An object is said to be unreachable if it doesn’t contain any reference from the program.
Garbage collection in Java happens automatically during the lifetime of the program.
Garbage collector is the best example of Daemon thread as it is always running in background.
Ways to make an object eligible for Garbage collection
Even though programmer is not responsible to destroy objects, It is highly recommended to make an object eligible for Garbage Collection, If it is no longer required. An object is eligible for Garbage Collection if it doesn’t contain any references. There are five ways to make an object eligible for garbage collection.
- Nullifying the reference variable
- Re-assigning the reference variable
- Object created inside method
- Anonymous object
- Island of Isolation
Nullifying the reference variable
If an object is no longer required then assign null to all its reference variables then that object is automatically eligible for garbage collection.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
package com.vidvaan.corejava.GC01.eligible; public class Example { private String objectName; public Example(String objectName) { super(); this.objectName = objectName; } public void process() { System.out.println(this.objectName + " process !!!"); } @Override protected void finalize() throws Throwable { System.out.println(this.objectName + " garbage collected successfully !!!"); } @Override public String toString() { return "Example [objectName=" + objectName + "]"; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
package com.vidvaan.corejava.GC01.eligible; // Nullifying the reference variable to make object eligible for GC public class NullifyReferencesDemo { public static void main(String[] args) { System.out.println("main begin"); Example example = new Example("Example1"); // example object used for processing something example.process(); // When there is no more use of 'example', make object eligible for garbage // collection by assigning 'null' example = null; // Requesting JVM to invoke Garbage Collector System.gc(); System.out.println("main end"); } } |
Re-assigning the reference variable
If an object is no longer required then reassign its reference variable to some other object then the old object eligible for garbage collection.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package com.vidvaan.corejava.GC01.eligible; // Re-assigning the reference variable to make object eligible for GC public class ReassigningReferenceDemo { public static void main(String[] args) { System.out.println("main begin"); Example example1 = new Example("Example1"); Example example2 = new Example("Example2"); // example1 object used for processing something example1.process(); // If example1 object is no longer required // example1 now referred to example2 // Now example1 is eligible for garbage collection example1 = example2; // Requesting JVM to invoke Garbage Collector System.gc(); System.out.println("main end"); } } |
Object created inside method
The objects created inside a method are by default eligible for garbage collection once method completes its execution.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
package com.vidvaan.corejava.GC01.eligible; // Object created inside a method to make object eligible for GC public class ObjectCreatedInsideMethodDemo { public static void main(String[] args) { System.out.println("main begin"); // what ever the objects created inside createAndDisplay() are eligible for GC // on it completes it's execution createAndDisplay(); // Requesting JVM to invoke Garbage Collector System.gc(); System.out.println("main end"); } public static void createAndDisplay() { // object 'example' becomes unreachable when method createAndDisplay() completes // its execution Example example = new Example("Example1"); System.out.println(example); } } |
Anonymous object
If we create an object without any reference variable then it becomes unreachable.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
package com.vidvaan.corejava.GC01.eligible; // Anonymous object to make object eligible for GC public class AnonymousObjectDemo { public static void main(String[] args) { System.out.println("main begin"); // create an object without any reference variable then it is eligible for GC new Example("Eample1"); // Requesting JVM to invoke Garbage Collector System.gc(); System.out.println("main end"); } } |
Island of Isolation
Island of isolation is a group of objects that reference each other but they are not referenced by any active object in the application.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
package com.vidvaan.corejava.GC01.eligible; // Island of Isolation to make object eligible for GC public class IslandOfIsolationDemo { public static void main(String[] args) { System.out.println("main begin"); Sample sample1 = new Sample(); Sample sample2 = new Sample(); // Object of sample1 gets a copy of sample2 sample1.sample = sample2; // Object of sample2 gets a copy of sample1 sample2.sample = sample1; // Now both sample1, sample2 have references from program // Assign 'null' to 'sample1' sample1 = null;// now 'sample1' Object not have references from program, But it got referred by // 'sample2' and 'sample2' have reference from program. So both 'sample1' and // 'sample2' not eligible for GC // Assign 'null' to 'sample2' sample2 = null;// now both 'sample1' and 'sample2' not have references from program, But they // refer each other, Still they are But they both are eligible for GC, because // they don't have references from the program // Requesting JVM to invoke Garbage Collector System.gc(); System.out.println("main end"); } } class Sample { Sample sample; @Override protected void finalize() throws Throwable { System.out.println("Sample.finalize()"); } } |
Ways for requesting JVM to run Garbage Collector
Whenever we made an object eligible for GC, it may not be destroyed immediately by the garbage collector. Whenever JVM runs the GC then only unreached object will be destroyed. But we can’t expect exactly when JVM runs GC.
Instead of waiting until JVM runs GC, we can request JVM to run GC programmatically.
- System.gc()
- Runtime.getRuntime().gc()
There is no guarantee that any one of above two methods will definitely run Garbage Collector.
System.gc()
System class contain static method gc() for requesting JVM to run Garbage Collector.
1 |
System.gc(); // static method |
Runtime.getRuntime().gc()
Runtime class allows the application to interact with the JVM. We can use gc() method to request JVM to run Garbage Collector.
1 |
Runtime.getRuntime().gc(); // instance method |
It is recommended to use System.gc() over Runtime.gc()
Finalization
The finalize() method is a special method which is called by the garbage collector on an object which is eligible for Garbage Collection. Object is eligible for garbage collection when there are no more references to the object(unreferenced object). Once the finalize() method completes, immediately Garbage Collector destroy that object. finalize() method is defined in java.lang.Object class and its syntax is as follows.
1 |
protected void finalize() throws Throwable { } |
finalize() method is used to perform clean-up activity. Clean-up activity could be resource releasing(DB Connection, Network Connection, File, stream … etc.).
Since Object class contains the finalize() method it inherits into every java object. So Garbage Collector calls finalize() method on all java objects.
The finalize method in the Object class, has an empty implementation. If we have clean-up activities in our class then we have to override this method to define our own clean-up activities.
Example 01 : finalize() method called by Garbage Collector
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
package com.vidvaan.corejava.exception11.FinalVsFinallyVsFinalize; // Garbage Collector - invokes finalize() method public class Example01FinalizeMethodCalledByGC { // This method executed by Garbage Collector just before this object Garbage // Collected @Override protected void finalize() throws Throwable { System.out.println("finalize() method"); } public static void main(String[] args) throws Exception { Example01FinalizeMethodCalledByGC object = new Example01FinalizeMethodCalledByGC(); object = null; System.gc(); // Requesting JVM to invoke Garbage Collector Thread.sleep(1000); // To make sure Garbage Collector gets chance from thread scheduler } } |
Output :
finalize() method
In the above example, we are calling System.gc(); for requesting JVM to invoke Garbage Collector. But there is no guarantee that always garbage collector executes with System.gc().
Example 02 : Explicitly invoke finalize() method
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
package com.vidvaan.corejava.exception11.FinalVsFinallyVsFinalize; //Explicitly invoke finalize() method public class Example02ExplicitlyCallFinalizeMethod { @Override protected void finalize() throws Throwable { System.out.println("finalize() method"); } public static void main(String[] args) throws Throwable { Example02ExplicitlyCallFinalizeMethod object = new Example02ExplicitlyCallFinalizeMethod(); System.out.println("main begin"); // Calling finalize method Explicitly. object.finalize(); // To make sure object is not destroyed after explicit call of finalize() method object.toString(); // If this lines executes it is the proof that object is not destroyed object = null; // Requesting JVM to invoke Garbage Collector System.gc(); System.out.println("main end"); } } |
Output :
main begin
finalize() method
main end
finalize() method
In the above example, As we are invoking finalize() method explicitly, object won’t get destroyed. To prove that, after calling finalize() method explicitly we are calling toString(); method, it executed without fail. It proves that when we invoke finalize() method explicitly that method will be executed like a normal method.
Example 03 : Explicitly invoke finalize() method – exception raised in finalize() execution
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
package com.vidvaan.corejava.exception11.FinalVsFinallyVsFinalize; // finalize() method explicit call - exception raised in finalize() method execution public class Example03ExplicitlyCallFinalizeUncheckedExceptionRaised { @Override protected void finalize() throws Throwable { System.out.println("finalize() method begin"); int result = 5 / 0; // It will throw unchecked ArithmeticException, program gets terminated System.out.println("finalize() method end"); } public static void main(String[] args) throws Throwable { Example03ExplicitlyCallFinalizeUncheckedExceptionRaised object = new Example03ExplicitlyCallFinalizeUncheckedExceptionRaised(); System.out.println("main begin"); // Calling finalize() method Explicitly. object.finalize(); System.out.println("main end"); } } |
Output :
main begin
finalize() method begin
Exception in thread “main” java.lang.ArithmeticException: / by zero
at com.vidvaan.corejava.exception11.FinalVsFinallyVsFinalize.Example03ExplicitlyCallFinalizeUncheckedExceptionRaised.finalize(Example03ExplicitlyCallFinalizeUncheckedExceptionRaised.java:9)
at com.vidvaan.corejava.exception11.FinalVsFinallyVsFinalize.Example03ExplicitlyCallFinalizeUncheckedExceptionRaised.main(Example03ExplicitlyCallFinalizeUncheckedExceptionRaised.java:20)
In the above example, We are calling finalize() method explicitly and we can see that program terminated as there is exception raised in finalize() method execution.
Exception could be checked or unchecked program gets terminated when we invoke finalize() method explicitly.
Example 04 : finalize() method called by GC – exception raised in finalize() execution
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package com.vidvaan.corejava.exception11.FinalVsFinallyVsFinalize; // finalize() method called by Garbage collector - exception raised in finalize() execution public class Example04GCCallFinalizeMethodUncheckedRaised { @Override protected void finalize() throws Throwable { System.out.println("finalize() method begin"); int result = 5 / 0; // It will throw unchecked ArithmeticException, remaining lines ignored System.out.println("finalize() method end"); } public static void main(String[] args) throws Throwable { Example04GCCallFinalizeMethodUncheckedRaised object = new Example04GCCallFinalizeMethodUncheckedRaised(); System.out.println("main begin"); object = null; // Requesting JVM to invoke Garbage Collector System.gc(); System.out.println("main end"); } } |
Output :
main begin
main end
finalize() method begin
In the above example, Garbage Collector calling finalize() method. We can see that program not terminated even exception raised in finalize() method execution. But note that, after exception raised remaining lines of finalize() method are ignored and even exception is not displayed in the console.
Exception could be checked or unchecked remaining lines of finalize() method are ignored and exception details will not be printed on the console when finalize() method invoked by Garbage Collector.