When you create an object by instantiating a class, the object uses some memory. After an object in memory has been used and is no longer needed, it is sensible to free memory from that object. Unlike some object-oriented languages where you have to explicitly destroy the objects that are no more references to that object. References that held in a variable naturally dropped when the variable goes out of scope. Alternatively, we can explicitly drop an object reference by setting the variable to null. which is a tedious and error-prone task, Java follows a different approach.
Java allows you to create as many objects as you want without any worry about destroying them. The Java Runtime Environment (JRE) deletes objects automatically when it determines that they no longer used. The objects which no longer used termed as garbage, and the process of deleting these objects automatically is known as garbage collection.
The Java garbage collector is a mark-sweep garbage collector. It scans active memory areas for objects and marks those that are referenced and then all the unmarked objects Le. Unreferenced objects which considered as garbage are collected.
A separate garbage collector thread always runs at low priority. It can run both synchronously and asynchronously. It runs synchronously when the system resources are low or when it has been forced to run by a call to the collector.
This garbage collector thread checks the dynamic memory area and marks all those areas that are referenced. After sweeping through the area, it cleans up all the areas that were not referenced. It checks all possible areas in which the objects could have been referenced. The garbage collector normally calls the object’s finalize method if one was written, before it works on that object. This allows the object itself to clean up all the system resources that it allocated.
The Java runtime environment runs the garbage collector automatically. But if your program requires that the garbage collector is run at a particular convenient time, you can force it using the System.gc() method.
An object is eligible for garbage collection when
• You drop an object reference by setting the variable to a special value null.
• As soon as the variable goes out of scope, the references in the variable are automatically dropped.
In Java, the memory is allocated to the objects using ‘new’ operator. In languages like C++, the memory is deallocated using ‘delete’ operator. This process of deallocating memory is called garbage collection. Java deallocates the memory itself. When no reference to an object is found, the object is assumed to be not needed any more. So, the memory allocated to that object can be reclaimed. There is no need to explicitly destroy objects.
Garbage collection is done automatically using a garbage collector. The JVM executes its garbage collector for retrieving the memory of objects that no longer used so that the memory can use for other objects. Therefore, memory leaks which are common in C++ due to inability to perform automatic garbage collection are less likely in Java.
In other languages like C++, the programmer needs to ensure that an object’s memory is de-allocated. If the C++ programmer is not careful about these de-allocations, the program may end up with memory “leaks.” The ill effects of these are all too familiar-program crashes, more paging, swapping, slower system response time, and the like.
Garbage collection takes time, so the Java run-time system does it only when necessary. It does not occur just because one or more objects exist that no longer used. For efficiency, the garbage collector usually runs when there are objects to recycle, and there is a need to recycle them. You can’t know precisely when garbage collection takes place.
There may occur a situation when the object that destroyed the need to perform some action. To handle such situations, Java provides ‘a mechanism called finalization. So, we need to add a finalize () method to our class.
The finalize() method of an object is the opposite of its constructor. The finalize() method is where resources that are allocated by the object can free.
In Java, when an object no longer referenced, the Java runtime environment runs the object’s finalize() method before reclaiming the object’s memory. The programmer can also force this process synchronously by calling the following method:
System.runFinalization();
Every object has a default finalize() method associated with it. You can override the default behavior by writing code in an object’s finalize() method. Reasons to override default behavior include de-allocation of other resources that an object may have allocated, such as files, streams, and so on.
This default method is declared as follows:
protected void finalize() throws Throwable
NOTE. It is usually a good practice to call the finalize method of the superclass if the superclass has a finalize method. It enables the resources used by the superclass to be cleared up.
You can also call the finalize() method of an object in your program, as shown just below. It does not, however, guarantee that the object’s memory reclaimed immediately. That is a function of the garbage collector thread.
protected void finalize() throws Throwable {
// clean up code for this class here
super.finalize();
}
Finalize methods always have a return type of void and override a default destructor in java.object.Object.
Usually the finalize methods are used to free up all the system resources, closing up the files, sockets, and so on. Here a PrintStream and DataInput-Stream which opened earlier are closed in its finalize method.
We need not worry about the use of finalize () in our programs since it used in sporadic cases where the object is not under the control of the garbage collector.
A program can call finalize directly just as it would any other method. However, calling finalize not initiate any garbage collection. It treated like any other method called directly. When Java does garbage collection, finalize is still called even if it has already been called directly by the program.
The finalize method can be overloaded also. If Java finds a finalize method with arguments at garbage-collection time, it looks for a finalize method with no arguments. If it does not find one, Java uses the default finalize method instead.
The system only calls finalize when it is ready to reclaim the memory associated with the object and not immediately after an object no longer referenced. That is, finalize() is called only when the system is running short of memory so that it may be called long after the application finishes.