In old languages like C++ programmer is responsible for both the creation and destruction of objects. Usually, the programmer is taking very much care while creating objects and neglect the destruction of useless objects. Due to his negligence at a certain point of time for the creation of new objects sufficient memory may not be available and the entire application may be crashed due to memory problems.

But in java the programmer is responsible only for the creation of a new object and his not responsible for the destruction of objects. Sun people provided one assistant who is always running in the background for destruction at useless objects. Due to this assistant the chance of failing a java program is very rare because of memory problems. This assistant is nothing but a garbage collector. Hence the main objective of GC is to destroy useless objects.

The ways to make an object eligible for GC

Even though the programmer is not responsible for the destruction of objects but it is always a good programming practice to make an object eligible for GC if it is no longer required.

An object is eligible for GC if and only if it does not have any references.

The following are various possible ways to make an object eligible for GC.

1) . Nullifying the reference variable

If an object is no longer required then we can make eligible for GC by assigning "null" to all its reference variables.


2.Reassign the reference variable

If an object is no longer required then reassign all its reference variables to some other objects then the old object is by default eligible for GC.



Objects created inside a method

Objects created inside a method are by default eligible for GC once the method completes.




 

Island of Isolation


Note: if an object doesn't have any reference then it always eligible for GC. Note: Even though the object having reference still it is eligible for GC some times.

island of isolation. (Island of Isolation all references are internal references )

The methods for requesting JVM to run GC

Once we made an object eligible for GC it may not be destroyed immediately by the GC.

Whenever JVM runs GC then the only object will be destroyed by the GC. But when exactly JVM runs GC we can't expert it is vendor dependent.

We can request JVM to run a garbage collector programmatically, but whether JVM accepts our request or not there is no guaranty.

But most of the time JVM will accept our request.

The following are various ways for requesting JVM to run GC:

By System class

System class contains a static method GC for this purpose. Example: System.gc();

By Runtime class

A java application can communicate with JVM by using the Runtime object. Runtime class is a singleton class present in java.lang. Package. We can create a Runtime objects by using the factory method getRuntime(). Example: Runtime r=Runtime.getRuntime();

Once we got Runtime object we can call the following methods on that object.

freeMemory(): returns the free memory present in the heap. totalMemory(): returns total memory of the heap. gc(): for requesting jvm to run gc.

import java.util.Date;
import java.util.Date; class RuntimeDemo { public static void main(String args[]){ Runtime r=Runtime.getRuntime(); System.out.println("total memory of the heap :"+r.totalMemory()); System.out.println("free memory of the heap :"+r.freeMemory()); for(int i=0;i<10000;i++) { Date d=new Date(); d=null; } System.out.println("free memory of the heap :"+r.freeMemory()); r.gc(); System.out.println("free memory of the heap :"+r.freeMemory()); } }
output:
total memory of the heap :16252928 free memory of the heap :15648640 free memory of the heap :15393448 free memory of the heap :15882064

Just before destroying any object GC always calls finalize() method to perform cleanup activities. If the corresponding class contains finalize() method then it will be executed otherwise Object class finalize() method will be executed. which is declared as follows.

protected void finalize() throws Throwable

Case 1: Just before destroying any object GC calls finalize() method on the object which is eligible for GC then the corresponding class finalize() method will be executed.

For Example if the String object is eligible for GC then the String class finalize()method is executed but not Test class finalize()method.

public class Test
{ public static void main(String args[]){ String s=new String("bhaskar"); Test t=new Test(); s=null; System.gc(); System.out.println("End of main."); } public void finalize(){ System.out.println("finalize() method is executed"); } } Output: End of main.

In the above program String class finalize()method got executed. 

Which has an empty implementation?

If we replace the String object with Test object then Test class finalize() method will be executed.

The following program is an example of this.

public class Test
{ public static void main(String args[]){ String s=new String("Bala"); Test t=new Test(); t=null; System.gc(); System.out.println("End of main."); } public void finalize(){ System.out.println("finalize() method is executed"); } } Output: finalize() method is executed End of main

Case 2: We can call finalize() method explicitly then it will be executed just like a normal method call and object won't be destroyed. But before destroying any object GC always calls finalize() method.

pubic class Test
{ public static void main(String args[]){ Test t=new Test(); t.finalize(); t.finalize(); t=null; System.gc(); System.out.println("End of main."); } public void finalize(){ System.out.println("finalize() method called"); } } Output: finalize() method called. finalize() method called. finalize() method called. End of main.

In the above program finalize() method got executed 3 times in that 2 times explicitly by the programmer and one time by the GC.

Note: In Servlets we can call destroy() method explicitly from init() and service() methods. Then it will be executed just like a normal method call and the Servlet object won't be destroyed.



finalize() method can be call either by the programmer or by the GC.

Case:3

If the programmer calls explicitly finalize() method and while executing the finalize() method if an exception raised and uncaught then the program will be terminated abnormally.

If GC calls finalize() method and while executing the finalize()method if an exception raised and uncaught then JVM simply ignores that exception and the program will be terminated normally.

public class Test
{ public static void main(String args[]){ Test t=new Test(); //t.finalize();-------line(1) t=null; System.gc(); System.out.println("End of main."); } public void finalize(){ System.out.println("finalize() method called"); System.out.println(10/0); } } End of main. finalize() method called

If we do not comment line1 then programmer calling finalize() method explicitly and while executing the finalize()method ArithmeticException raised which is uncaught hence the program terminated abnormally. 

If we are comment line1 then GC calls finalize() method and JVM ignores ArithmeticException and the program will be terminated normally.

Which of the following is true?

While executing finalize() method JVM ignores every exception(invalid). While executing finalize() method JVM ignores only uncaught exception(valid).

Case 4: On any object GC calls finalize() method only once.

public class FinalizeDemo
{ static FinalizeDemo s; public static void main(String args[])throws Exception{ FinalizeDemo f=new FinalizeDemo(); System.out.println(f.hashCode()); f=null; System.gc(); Thread.sleep(5000); System.out.println(s.hashCode()); s=null; System.gc(); Thread.sleep(5000); System.out.println("end of main method"); } public void finalize() { System.out.println("finalize method called"); s=this; } } 1829164700 finalize method called 1829164700

Note: The behavior of the GC is vendor dependent and varied from JVM to JVM hence we can't expert exact answer for the following. What is the algorithm followed by GC. Exactly at what time JVM runs GC. In which order GC identifies the eligible objects. In which order GC destroys the object etc.

Whether GC destroys all eligible objects or not. Whenever the program runs with low memory then the JVM runs GC, but we can't except exactly at what time. Most of the GC's followed mark & sweep algorithm, but it doesn't mean every GC follows the same algorithm.

Memory leaks

An object which is not using in our application and it is not eligible for GC such type of objects is called "memory leaks".

In the case of memory leaks GC also can't do anything the application will be crashed due to memory problems.

In our program if memory leaks present then certain point we will get OutOfMemoryException.

Hence if an object is no longer required then it's highly recommended to make that object eligible for GC. By using monitoring tools we can identify memory leaks.

That's it. This is all about Garbage collection in Java.