When a Java program starts execution, the operating system assigns some memory to JVM. JVM uses this memory for all of its operations. Part of this memory is called heap memory. Whenever we create an object via '
new' operator, it is assigned some memory from the heap memory area. This heap memory area is globally accessible to all running threads. If all running threads take memory from the heap memory area for their object creation, there should be some mechanism to reclaim those memories, otherwise the heap memory will go out of stock. In programming languages like C++, if someone creates an object using the '
new' operator, then its the programmer's responsibility to keep track of the object and clear the memory via destructors once the object is not needed, otherwise it will cause memory leaks. But in Java, we do not have any explicit way of destroying an object. JVM takes care of this memory management itself and relieves the programmers from having to worry about memory leaks. It is essential for any programmer claiming to have good knowledge of Java programming, to know how garbage collection works behind the cloak.
Garbage collection is a mechanism to reclaim heap memory occupied by those objects which are not being used by any of the live threads of our program. JVM periodically runs a process called Garbage Collector which checks which objects are being used and which are not, and reclaims memories from unused objects and gives it back to the heap memory for future use. Apart from reclaiming memory from unused objects, garbage collector also ensures that objects having live references exist and thus avoids the situation called dangling reference.
When an Object Becomes Eligible for Garbage Collection
An object becomes eligible for garbage collection if is not reachable by any live thread or it is not being referenced by any other reachable objects. JVM assumes certain objects, known as roots, to be reachable. It then starts tracing out other reachable objects starting from these roots and mark them as live objects. At the end, it clears all other objects not marked as lives. Garbage collector does take into account cyclic dependency. If some object A is reachable from some other object B and object B is reachable from object A, but if both A and B are not reachable from any other live objects, then they both become eligible for garbage collection.
An object become eligible for garbage collection in the following scenarios:
- If the object is assigned a
null value like '
object = null', then it becomes eligible for garbage collection.
- If a parent object A contains a reference of object B, and if the object A is set to
null, then object B also becomes eligible for garbage collection.
- If the object is created inside a block and the program control goes out of the scope of the block, then the object becomes eligible for garbage collection.
Heap Memory Generations and Generational Garbage Collections
JVM breaks up the heap memory into smaller parts called generations. These are Young Generation, Old Generation and Permanent Generation. It divides Young Generation again into sub-smaller parts called Eden space, Survivor space 1 and Survivor space 2.
All newly created objects are first placed in the Young Generation. If they survive some number of garbage collections, then they are promoted to the Old Generation. Since, most of the objects survive for only a short duration of time and only few remain allocated over time, Young generation is more frequently garbage collected than the old generation.
The following steps describe how a newly allocated objects survive in the Young generation and get promoted to Old generation.
- When a new object is created, it is assigned memory from Eden space.
Both survivor space1(S1) and survivor space2(S2) start with empty allocation.
- When Eden space gets filled up, JVM runs one minor garbage collector which clears unreferenced objects and moves referenced ones to the first survivor space(S1).
Here green color represents referenced objects and red color indicates un-referenced ones. Upon moving to survivor space 1, referenced objects get their reference count incremented by one.
- Newly created objects are still assigned memory from Eden space. After second minor garbage collection, those objects who have live references in both Eden space and S1, are moved to S2 region.
- This way, the referenced objects keep on oscillating in between the survivor spaces, until they reach a threshold.
- After some time interval, if some objects survive some threshold limit(in this case 5), they are promoted to the old generation.
In this way, objects continue to get promoted to the old generation because of minor garbage collections. At the end, JVM runs a major garbage collector on the old generation which claims the memories occupied by unused objects and returns it back to the heap memory.