Before we understand the concept of Garbage Collection in Java, let's understand the concept of Stack and Heap memory.
Stack is a portion of the memory where the local primitive values/value type values, for example - int, char, long, bool or local object reference variables are stored
Heap is a portion of the memory where instances/objects and their instance variables are stored.
Objects and instance variables continue to live on Heap, as long as they are referenced by their reference variables.
Objects are stored in the Heap memory and heap is limited in space.
Now, let's imagine you have created a program that is creating thousands of objects on the heap,
such program could lead to a disaster for the heap memory especially if the unreferenced objects aren't deallocated from the heap memory.
If you were working in a programming languages like C, C++, you would have to write your own memory management code to make sure there is enough free space on heap
memory.
C# provides the facility of automaticgarbage collection through its facility - garbage collector
which makes sure that the unreferenced objects are taken off the heap memory and
thereby making sure that
there is enough of space on heap to store new objects to efficiently run programs.
How a garbage collector helps in memory management?
When the garbage collector runs, it frees up the space on heap memory by finding and deleting
those objects on it that are not referenced by any live program.
How do you make the garbage collector run?
Usually the garbage collectionautomatically runs when it finds the system to be running on a low physical
memory or it may even
run after the termination of a program because that's when it finds some unreferenced objects which
aren't referenced by a LIVE program in execution.
The garbage collector may not run right when run
we have some unreferenced objects in our program in execution(unless we force it to).
Note: Yes, we can even manually force the garbage collector to run by calling the Collect() method of the GC class.
The GC class encapsulates the garbage-collection facility.
An example of automatic execution Garbage Collection
Let's see an example in which we will create multiple objects of a class, by using its constructor, and we will define
the destructor of the class,
which will be automatically called right before any of the objects are taken off the memory
by the garbage collector.
// C# Example of Garbage Collection
using System;
class A
{
//Instance variable of class A
int num;
//Constructor of class A
A(int a)
{
num = a;
Console.WriteLine("Creating an object" + num);
}
//Destructor of class A
//This may run at the termination of the program
~A()
{
Console.WriteLine("Destructing an object" + num);
}
public static void Main(String[] ar)
{
//A for-loop to create 5 objects of class A
for(int i=0; i<5;i++)
{
//Calling the constructor of class A
//And passing a specific int value
//That is stored in the instance variable, num, of each object.
A ob = new A(i);
}
}
}
Output-
Creating an object0
Creating an object1
Creating an object2
Creating an object3
Creating an object4
Destructing an object4
Destructing an object0
Destructing an object3
Destructing an object2
Destructing an object1
Program Analysis
In this code above, we have created a class A with a constructor and a destructor.
Next, we have created 5 objects of this class, by calling the constructor
(once for each object), and passing a specific int value, which is stored in the instance variable, num, of each object.
Finally, upon the termination of the program, the garbage collector runs,
and calls the destructor of the class, before it takes the unreferenced object off the Heap memory.
Note: Although in this example, we have only created 5 objects but usually,
the garbage collector is activated when you are creating and destroying a large number of objects.
Advertisement
Manually forcing the execution of Garbage Collection
The GC class encapsulates the garbage-collection facility and using it,
we can even manually make the garbage collector to run by calling its Collect() method,
which will take the unreferenced objects off the memory, as many as possible.
We will also call the GetTotalMemory(bool forceFullCollection) of GC class, where:
When this method is passed the bool false value, it says that this method should first execute
and return the total number of bytes in the memory current used, without waiting for the Garbage Collector to execute.
When this method is passed the bool true value, it says that this method should first wait for the Garbage Collector to execute
and then return the total number of bytes in the memory current used.
//C# Manually forcing the execution of Garbage Collection
using System;
class A
{
public static void Main(String[] ar)
{
//Calling the GetTotalMemory() method with bool value, false
//Which says, this method should execute first
//and return the total number of bytes in the memory current used
//Without waiting for the Garbage Collector to execute.
//
Console.WriteLine("Amount of used memory at the beginning of program - " + GC.GetTotalMemory(false));
//Declaring an reference type of class A
A ob;
//Within this for loop, 100000 objects of class A will be created
//Out of which only the last object will be assigned reference, ob
//Rest 99999 will be left unreferenced
for(int i=0; i<100000;i++)
{
//Creating an object of class A
//And, assigning its reference to reference variable, ob
ob= new A();
}
//Calling the GetTotalMemory() method with bool value, false
//Which says, this method should execute first
//and return the total number of bytes in the memory current used
//Without waiting for the Garbage Collector to execute.
Console.WriteLine("Amount of used memory after creating 1000000 objects - " + GC.GetTotalMemory(false));
//Forcing the garbage collector to run.
//To collect all the unreferenced objects
GC.Collect();
//Calling the GetTotalMemory() method with bool value, true
//Which says, that this method can wait for the garbage collector to execute
//Before it returns the total amount of free memory
Console.WriteLine("Amount of used memory after running garbage collector - " + GC.GetTotalMemory(true));
}
}
Output-
Amount of used memory at the beginning of program - 47736
Amount of used memory after creating 1000000 objects - 2472568
Amount of used memory after running garbage collector - 55032
Program Analysis
In the preceding code, free memory is calculated at the beginning of the program by calling the
GetTotalMemory() method of GC class.
Next in for-loop, we have created 100000 objects of A class and, again the free memory is re-calculated.
When the for-loop ran for the last time, only then the last object is referenced by reference variable, ob.
Rest 99999 objects aren't referenced by any reference variable and they are good for garbage collection.
On the execution of Collect() method, garbage collector runs and it frees the memory,
which is proven by calling the GetTotalMemory() method of GC class.