Garbage Collection in Java

When you create an object by instantiating a class, the object is put on the heap; in other words, it uses some memory. A Java application creates and uses objects. After an object in memory has been used and is no longer needed, it is sensible to free memory from that object. The process of freeing memory from the used objects is called garbage collection. How do you accomplish this in Java?

In Java, garbage collection is done automatically by what is called the garbage collector.

Garbage Collector 

The garbage collector in Java automates memory management by freeing up the memory from objects that are no longer in use. The advantage of this is that you do not need to code the memory management into your application. The price you pay for this service is that you have no control over when the garbage collector runs. There are two things that you can do in the code to help memory management:
  • Make an object eligible for garbage collection, because a garbage collector will only free up memory from an eligible object.
  • Make a request for garbage collection by making a system call to the garbage collector: System.gc();
You can also invoke the gc() method by using an instance of the Runtime class that a running application always has. You get hold of this instance by calling the static method getRuntime() of the Runtime class:

   Runtime rt = Runtime.getRuntime();

Then, you can use this instance to invoke methods in order to perform some runtime tasks, such as to get memory information or to run the garbage collector:


These uses of the Runtime class are demonstrated in below code snippet:

1. class RuntimeTest {
2.    public static void main (String [] args) {
3.         Runtime rt = Runtime.getRuntime();
4.   System.out.println("JVM free memory before running gc: "+  rt.freeMemory());

5.        rt.gc();
6.  System.out.println("JVM free memory after running gc:" + rt.freeMemory());
7.   }
8. }

Remember that an application cannot create its own instance of the Runtime class. Therefore the following code will be invalid:

   new Runtime().gc(); 

A call to the garbage collector is no guarantee that the memory will be free. It is possible, for example, that the JVM in which your program is running did not even implement the gc() method. The Java language specification allows a dummy gc() method.

The basic requirement for garbage collection is that you must make your object eligible for garbage collection. An object is considered eligible for garbage collection when there is no reference pointing to it. You can remove the references to an object in two ways:
Set the object reference variable pointing to the object to null; for example:

   myObject = null; 

Reassign a reference variable of an object to another object. For example, if a reference variable myObject is pointing to an object of the MyClass class, you can free this object from this reference by pointing the reference to another object: 

  myObject = new YourClass(); 

Now, the object reference myObject is pointing to an object of the class YourClass and not to an object of MyClass, to which it was pointing previously.
What if you want an object to clean up its state before it is deleted? Well, you can declare the finalize() method in the class, and this method will be called by the garbage collector before deleting any object of this class.

The finalize() Method 

The object that has no object references pointing to it can be deleted by the garbage collector to reclaim the memory. If the object has a finalize() method, it will be executed before reclaiming the memory in order to give the object a last chance to clean up after itself—for example, to release the resources that the object was using.

The finalize() method is inherited from the Object class by any class you define. The signature of the finalize() method in the object class is shown here: 

   protected void finalize();

You can override this method in your class. The Java programming language specifies that the finalize() method will be called before the object memory is reclaimed, but it does not guarantee exactly when it will happen. Remember that the finalize() method that your class inherited does not do anything. If you want your object to clean up after itself, you have to override the finalize() method. Then, what is the point of putting the finalize() method in the Object class? It makes it safe for the finalize() method of any class to invoke the finalize() of the superclass, as shown here:

   protected void finalize() {
      // clean up code follows

This is generally a good practice. 
When an object is instantiated from a class, it is called reachable and unfinalized. When no reference is pointing to an object, the object can only be reached by the finalize() method, and hence it is called finalizer reachable. However, it is possible to make the object reachable again for any live thread
by creating a reference to this object in its finalize() method. 

The finalize() method for an object is only run once. If you make an object ineligible for garbage collection in its finalize() method, it does not mean that the object will never be garbage collected because its finalize() method now will
never be called. 

The object can still become eligible for garbage collection when it has no reference pointing to it. The only difference is that, this time, the garbage collector will remove it without calling its finalize() method, because it has already been called. The garbage collector is not guaranteed to be invoked, and thus the finalize() method is not guaranteed to be called. It is a good practice for you, the programmer, to free up the resources when they are no longer required. 

Reference(s): SCJP Exam for J2SE 5 

No comments:

Post a Comment