In this article we will learn about garbage collection, which is a mechanism for freeing the memory occupied by objects which are no longer used in a program.
In most of the object oriented programming languages, memory management (allocating and deallocating memory) is left to the user and it is generally error prone (user might forget to free the memory occupied by an object). Objects are allocated memory in the heap memory which grows and shrinks dynamically. Java provides automatic memory management through a mechanism known as garbage collection.
Unused objects are collected for garbage collection by the program known as garbage collector. Java has its own set of algorithms which decides whether an object is eligible for garbage collection or not. Generally, an object is garbage collected when it goes out of scope or when the object is no longer referenced.
The garbage collector frequently scans the heap memory for detecting unused objects. Two general methods used by garbage collectors for finding unused objects are: reference counting and tracing.
In reference counting method, whenever an object is created, its reference count will be 1. As the object is referenced by other references, the reference count will be incremented by 1 for reference. As the references decrease, the reference count will be decremented. When the reference count is finally 0, the object will be garbage collected. Let’s consider the following code segment as an example:
public static void main(String args)
Square s1 = new Square();
Square s2 = new Square();
s1 = s2;
Following memory representation illustrates the reference count for each object:
In tracing method, also known as mark and sweep method, the garbage collector scans the dynamic memory areas for all the objects. The mark phase marks all the objects which are being referenced. After the marking is completed, the sweep phase frees the memory allocated to all other unmarked objects.
The garbage collectors using mark and sweep method uses compaction and copying (related to operating system memory management). During the sweep phase, the memory might get fragmented. The garbage collector moves all the fragmented memory towards one end (compaction) so that the other end contains a free block of memory which can be used by other code. Any other objects on the other side of the used memory are copied to this side (copying).
The garbage collector can run synchronously when the program runs out of memory or asynchronously when the system is idle. The garbage collector is an example of daemon thread (a thread which runs in the background).
Garbage collector can be explicitly invoked by using System.gc() or Runtime.gc(). Explicit invocation doesn’t guarantee that unused objects will be garbage collected. It is up to Java Virtual Machine when the unused objects will be actually freed.
It is common in Java programs to access files and databases (will be covered in future articles). It is also common for programmers to open the files and other resources and forget to close the connections to those resources. The code which is used to close the connections to resources like files, databases etc… is known as cleanup code or housekeeping code.
The cleanup code is generally written in the finalize() method which belongs to the Object class, as the finalize() method is guaranteed to be executed when the object gets cleaned up from the memory. This process is known as finalization.