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

This article is shared from the Huawei Cloud Community " article takes you to understand the garbage collection mechanism ", author: Haiyong.

introduce

• In C/C++, the programmer is responsible for the creation and destruction of objects. Usually programmers ignore the destruction of useless objects. Due to this oversight, at some point, in order to create a new object, there may not be enough memory available, and the entire program will terminate abnormally, resulting in OutOfMemoryErrors .
• But in Java, the programmer does not 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 release the heap memory object

Important terms:

  • inaccessible object : If an object does not contain any reference to it, it is said to be an inaccessible object. Please also note that objects belonging to the isolated island are also inaccessible.
Integer i = new Integer(4);
// 新的 Integer 对象可通过 'i' 中的引用访问
i = null;
// Integer 对象不再可用。

image.png

  • Garbage Collection : If the object cannot be accessed, the object is said to be eligible for GC (garbage collection). In the above figure, after i = null; the integer object 4 in the heap area is eligible for garbage collection.

Methods to make objects eligible 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 generally four different ways to make objects suitable for garbage collection.

  1. Dereference variable
  2. Reallocate reference variables
  3. Object created inside the method
  4. Isolation island

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

How to request the JVM to run the garbage collector

• Once we make the object eligible for garbage collection, the garbage collector may not immediately destroy it. Whenever the JVM runs the garbage collector program, only the object is destroyed. But when the JVM runs Garbage Collector, we can't predict it.
• We can also request the JVM to run the garbage collector. There are two ways to do it:

  1. uses the System.gc() method. : The system class contains a static method gc() to request the JVM to run the garbage collector.
  2. uses 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.
// 演示请求 JVM 运行垃圾收集器的 Java 程序
public class Test
{
    public static void main(String[] args) throws InterruptedException
    {
        Test t1 = new Test();
        Test t2 = new Test();
 
        // 取消引用变量
        t1 = null;
 
        // 请求 JVM 来运行垃圾收集器
        System.gc();
 
        // 取消引用变量
        t2 = null;
 
        // 请求 JVM 来运行垃圾收集器
        Runtime.getRuntime().gc();
 
    }
 
    @Override
    // 在垃圾回收之前,在对象上调用一次 finalize 方法
    protected void finalize() throws Throwable
    {
        System.out.println("垃圾收集器调用");
        System.out.println("对象垃圾收集:" + this);
    }
}

Output:

垃圾收集器调用
对象垃圾收集:haiyong.Test@7ad74083
垃圾收集器调用
对象垃圾收集:haiyong.Test@7410a1a9

notes:

• There is no guarantee that either of the above two methods will always run the garbage collector.
• Calling System.gc() is equivalent to calling: Runtime.getRuntime().gc()

finalized

• Just before destroying the object, the garbage collector calls the finalize() method of the object to perform cleanup activities. Once the finalize() method is completed, the garbage collector will destroy the object.
• The finalize() method exists in the Object class with the following prototype.

protected void finalize() throws Throwable

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

notes:

  1. The finalize() method called by the garbage collector instead of the JVM. Although the garbage collector is one of the JVM modules.
  2. The object class finalize() method has a free implementation, so it is recommended to override the finalize() method to handle system resources or perform other cleanups.
  3. For any given object, the finalize() method will never be called multiple times.
  4. If the finalize() method throws an uncaught exception, ignore the exception and terminate the finalization of the object.

For an example of the finalize() method, please refer to the tenth set of garbage collection in the output of the Java program

Let us give a real example, where we use the concept of garbage collector.

Suppose you go to ByteDance for an internship, and they tell you to write a program to count the number of employees working in the company (not including interns). To make this program, you must use the concept of a garbage collector.

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

Q: write a program to create a class named Employee, this class has the following data members.
1. An ID, used to store the unique ID assigned to each employee.
2. The name of the employee.
3. Age of employees.

In addition, the following methods are provided-

  1. The parameterized constructor used to initialize the name and age. ID should be initialized in this constructor.
  2. The method show() to display ID, name, and age.
  3. The showNextId() method to display the ID of the next employee.

Beginners who are not familiar with the garbage collection mechanism may write code like this:

//计算在公司工作的员工人数的程序

class Employee
{
    private int ID;
    private String name;
    private int age;
    private static int nextId=1;
    //它是静态的,因为它在所有对象之间保持通用并由所有对象共享
    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();
 
            { //这是保留所有实习生的子块。
            Employee X=new Employee("GFG4",23);    
            Employee Y=new Employee("GFG5",21);
            X.show();
            Y.show();
            X.showNextId();
            Y.showNextId();
        }
        //这个大括号之后,X 和 Y 将被移除。因此现在它应该显示 nextId 为 4。
        E.showNextId();//这一行的输出应该是 4,但它会给出 6 作为输出。
    }
}

now gets the correct output:

Now the garbage collector (gc) will see 2 free objects. Now decrement nextId, gc(garbage collector) will only call method finalize() when our programmers overwrite it in our class. As mentioned earlier, we must request gc (garbage collector), for this, we must write the following 3 steps before closing the braces of the sub-block.

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

Now the correct code for calculating the number of employees (not including interns)

// 计算不包括实习生的员工人数的正确代码
class Employee
{
    private int ID;
    private String name;
    private int age;
    private static int nextId=1;
    //它是静态的,因为它在所有对象之间保持通用并由所有对象共享
    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;
        //在这种情况下,gc 会为 2 个对象调用 finalize() 两次。
    }
}

// 它是 Employee 类的右括号
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();
 
        {
            //这是保留所有实习生的子块。
            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 to follow, and learn about Huawei Cloud's fresh technology for the first time~


华为云开发者联盟
1.4k 声望1.8k 粉丝

生于云,长于云,让开发者成为决定性力量