Interview must ask: Java garbage collection mechanism

Keywords: Java jvm Interview

Absrtact: the garbage collection mechanism is the best example of a daemon thread because it always runs in the background.

This article is shared from Huawei cloud community< This article takes you to understand the garbage collection mechanism in Java >, author: Hai Yong.

introduce

  • In C/C + +, programmers are responsible for the creation and destruction of objects. Usually programmers ignore the destruction of useless objects. Due to this negligence, at some time, there may not be enough memory available to create new objects, and the whole program will terminate abnormally, resulting in OutOfMemoryErrors.
  • But in Java, programmers don't need to care about all objects that are no longer used. The garbage collection mechanism automatically destroys these objects.
  • The garbage collection mechanism is the best example of a daemon thread because it always runs in the background.
  • The main goal of the garbage collection mechanism is to free heap memory by destroying inaccessible objects.

Important terms:

  • Unreachable object:   If an object does not contain any references to it, it is called an inaccessible object. Also note that objects belonging to the isolated island are also inaccessible.
Integer i = new Integer(4);
// The new Integer object is accessible through a reference in 'i'
i = null;
// The Integer object is no longer available.

  • Eligibility for garbage collection:   If an object is inaccessible, it is said to be eligible for GC (garbage collection). In the above figure, after i = null;   Integer objects 4 in the heap area are eligible for garbage collection.

Methods to qualify objects for GC

  • Even if the programmer is not responsible for destroying useless objects, it is strongly recommended to make the objects inaccessible (and therefore eligible for GC) if they are no longer needed.
  • There are usually four different ways to make objects suitable for garbage collection.
  1. Dereference variable
  2. Reassign reference variables
  3. An object created inside a method
  4. Isolated island

All of the above methods with examples are discussed in a separate article: how to make objects eligible for garbage collection

How the JVM is requested to run the garbage collector

  • Once we qualify an object for garbage collection, the Garbage Collector may not destroy it immediately. Whenever the JVM runs the Garbage Collector program, only the object is destroyed. But when the JVM runs Garbage Collector, we can't predict.
  • We can also request the JVM to run the garbage collector. There are two ways to do this:
  1. Using System.gc()   Method: the system class contains the static method gc()   Used to request the JVM to run the garbage collector.
  2. Use Runtime.getRuntime().gc()   Method: the runtime class allows the application to interact with the JVM running the application. Therefore, by using its GC () method, we can request the JVM to run the garbage collector.
// Demonstrates a Java program that requests the JVM to run the garbage collector
public class Test
{
	public static void main(String[] args) throws InterruptedException
	{
		Test t1 = new Test();
		Test t2 = new Test();
 
		// Dereference variable
		t1 = null;
 
		// Request the JVM to run the garbage collector
		System.gc();
 
		// Dereference variable
		t2 = null;
 
		// Request the JVM to run the garbage collector
		Runtime.getRuntime().gc();
 
	}
 
	@Override
	// Call the finalize method on the object once before garbage collection
	protected void finalize() throws Throwable
	{
		System.out.println("Garbage collector call");
		System.out.println("Object garbage collection:" + this);
	}
}

Output:

Garbage collector call
 Object garbage collection: haiyong.Test@7ad74083
 Garbage collector call
 Object garbage collection: haiyong.Test@7410a1a9

Notes:

    1. There is no guarantee that either of these methods will run the garbage collector.
    2. Call System.gc()   Equivalent to calling: Runtime.getRuntime().gc()

Finalization

  • Just before destroying the object, the garbage collector calls finalize() of the object   Method to perform cleanup activities. Once finalize ()   Method, the garbage collector destroys the object.
  • finalize()   Method exists in the Object class with the following prototype.
protected void finalize() throws Throwable

According to our requirements, we can override finalize()   Method to perform our cleanup activities, such as closing the database connection.

Notes:

  1. finalize() called by the garbage collector instead of the JVM   method. Although the garbage collector is one of the modules of the JVM.
  2. Object class   finalize()   Method has empty implementation, so it is recommended to override finalize()   Method to process system resources or perform other cleanup.
  3. For any given object, finalize()   Method will never be called more than once.
  4. If finalize()   Method, ignore the exception and terminate the termination of the object.

About finalize()   Method, see the tenth set of garbage collection for the output of Java programs

Let's take a real example, where we use the concept of garbage collector.

Suppose you go to an internship, they tell you to write a program to calculate the number of employees working in the company (excluding interns). To make this program, you must use the concept of garbage collector.

This is the actual task you get at the company:-

Q:   Write a program to create a class called Employee that has the following data members.
1. An ID used to store the unique ID assigned to each employee.
2. Employee name.
3. Employee age.

In addition, the following methods are provided-

  1. A parameterized constructor for initializing names and ages. ID should be initialized in this constructor.
  2. The method to display ID, name and age is show().
  3. The method showNextId() that displays the ID of the next employee.

Beginners who do not understand garbage collection mechanism may write code like this:

//Procedure for calculating the number of employees working in the company

class Employee
{
	private int ID;
	private String name;
	private int age;
	private static int nextId=1;
	//It is static because it remains common among all objects and shared by all objects
	public Employee(String name,int age)
	{
		this.name = name;
		this.age = age;
		this.ID = nextId++;
	}
	public void show()
	{
		System.out.println
		("Id="+ID+"\nName="+name+"\nAge="+age);
	}
	public void showNextId()
	{
		System.out.println
		("Next employee id will be="+nextId);
	}
}
class UseEmployee
{
	public static void main(String []args)
	{
		Employee E=new Employee("GFG1",33);
		Employee F=new Employee("GFG2",45);
		Employee G=new Employee("GFG3",25);
		E.show();
		F.show();
		G.show();
		E.showNextId();
		F.showNextId();
		G.showNextId();
 
			{ //This is a sub block that retains all interns.
			Employee X=new Employee("GFG4",23);	
			Employee Y=new Employee("GFG5",21);
			X.show();
			Y.show();
			X.showNextId();
			Y.showNextId();
		}
		//After this brace, X and Y will be removed. So now it should show nextId 4.
		E.showNextId();//The output of this line should be 4, but it gives 6 as the output.
	}
}

Now get the correct output:

The garbage collector (gc) will now see two free objects. Now decrementing nextId, gc(garbage collector) will only call the method finalize() when our programmer overwrites it in our class. As mentioned earlier, we must request gc(garbage collector). To do this, we must write the following three steps before closing the braces of the sub block.

  1. Set the reference to null (that is, X = Y = null;)
  2. Call, System.gc();
  3. Call System.runFinalization();

Now the correct code to calculate the number of employees (excluding interns)

// Correct code to calculate the number of employees excluding interns
class Employee
{
	private int ID;
	private String name;
	private int age;
	private static int nextId=1;
	//It is static because it remains common among all objects and shared by all objects
	public Employee(String name,int age)
	{
		this.name = name;
		this.age = age;
		this.ID = nextId++;
	}
	public void show()
	{
		System.out.println
		("Id="+ID+"\nName="+name+"\nAge="+age);
	}
	public void showNextId()
	{
		System.out.println
		("Next employee id will be="+nextId);
	}
	protected void finalize()
	{
		--nextId;
		//In this case, gc calls finalize() twice for two objects.
	}
}

// It is the closing bracket of the Employee class
class UseEmployee
{
	public static void main(String []args)
	{
		Employee E=new Employee("GFG1",33);
		Employee F=new Employee("GFG2",45);
		Employee G=new Employee("GFG3",25);
		E.show();
		F.show();
		G.show();
		E.showNextId();
		F.showNextId();
		G.showNextId();
 
		{
			//This is a sub block that retains all interns.
			Employee X=new Employee("GFG4",23);	
			Employee Y=new Employee("GFG5",21);
			X.show();
			Y.show();
			X.showNextId();
			Y.showNextId();
			X = Y = null;
			System.gc();
			System.runFinalization();
		}
	E.showNextId();
	}
}

Click focus to learn about Huawei cloud's new technologies for the first time~

Posted by purinkle on Mon, 27 Sep 2021 19:47:29 -0700