This question came to me when I was reading the Interview with Niu Tourists, and WAS specially arranged in my regular interview question documents. Therefore, this question mainly examines the influence of Finalize method.

Java provides a finalize method to help with resource release, similar to the destructor in C++. But the current general understanding is not to use, why? This is because of the impact on Java virtual machine garbage collection. This article gives an illustration of it.

First, why does it matter

As we all know, if an object GCRoot is unreachable, the Java virtual machine considers it to be garbage and will recycle it. However, if the object contains Finalize function, its nature is different. Why is it different?

When Java VIRTUAL machine is garbage collecting, when Java virtual machine sees the Object class containing Finalize function, it will give FinalizerThread the finalize function, and then the objects containing Finalize function will be added to FinalizerThread’s execution queue and use a linked list. String together these objects with Finalize.


His influence lies in that as long as Finalize is not executed, these objects will always exist in the heap area. However, there are only 4 objects containing Finalize, so the influence is not so big. What if there are 10,000 or 100,000 objects? That makes a big difference.

The principle of Finalize is actually very simple. Here is a brief review of finalize:

(1) In the process of initialization, objects will determine whether Finalize is overwritten by has_finalizer_flag and RegisterFinalizersAtInit.

(2) If Finalize is overwritten, the current object should be registered in the ReferenceQueue queue of FinalizerThread. The registered object is called a Finalizer. The method is to call the register_finalizer function. At this point, the Java virtual machine sees that it currently has a reference to the object and does not do garbage collection.

(3) The object is called and the FinalizerThread is responsible for retrieving the Finalizer object from the ReferenceQueue queue. Start to execute the Finalize method, and the object stays in the heap until it executes.

(4) After the Finalizer object is executed, the Finalizer object is removed from the queue, and the Java VIRTUAL machine sees that the object is no longer referenced, and then garbage collects it.

That’s the whole process. However, we mainly look at the influence of Finalize method on garbage collection. In fact, in the third step, when finalize method is included in the object, it will occupy memory all the time when it is in the queue but has not been called.

Note: This is actually an interview question. I was looking at an interview on Niuke and saw that someone had been asked. Are GCRoot unreachable objects immediately garbage collected?

We use a case to analyze a wave:

Ii. Case demonstration

Let’s create a class

public class TestFinalizer {

    public static class Fdd {

     1 m / / distribution

        private byte[] content = new byte[1024*1024];

        @Override

        protected void finalize(a) {

            System.out.println("Finalize to be executed");

        }

    }

    public static void main(String[] args) {   

        for (int i = 0; i < 1000; i++) {

         Fdd fdd = new Fdd(); 

        }

    }

}

Copy the code

Now that the class is created, let’s set the parameters.

# the maximum heap memory - Xmx5m # # minimum heap memory - Xms5m heap memory overflow error print - XX: + HeapDumpOnOutOfMemoryError # the heap related information stored in the following path - XX: HeapDumpPath = F: / a. d. ump partyCopy the code

In the main method, 1000 Fdd objects are created. If finalize method is not implemented, garbage collection will be carried out because there is no call. At this time, there will be no problem if we create as many objects as possible. But if there is a Finalize method, it is different.

java.lang.OutOfMemoryError: Java heap space Dumping heap to F:/a.dump ... Finalize executed Finalize executed Finalize executed Finalize executed Finalize executed Finalize executed Finalize executed Execute Unable to create F:/ a.dunk: File exists Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at com.fdd.chapter2.TestFinalizer$Fdd.<init>(TestFinalizer.java:6) at com.fdd.chapter2.TestFinalizer.main(TestFinalizer.java:14)Copy the code

We see that every object will execute Finalize, and it will be in the heap until finalize is executed, and it will be cleaned up after finalize is executed, so you see here that Finalize method is executed no less than 5 times. But as soon as the object exceeds the 5M we set, it will run out of memory. In a word, object stacking occurs. Now use the MAT tool to analyze it.

The Mat tool is a plug-in, or you can download one yourself. Once the download is complete, open the A.dunk we just generated.

Here’s the result:


The content of section A is Finalizer, which is also our Fdd object, while SECTION B contains a lot of messy remaining information. Of course, you can also check out some other information. It’s all on the MAT tool. There are also some finalizers in progress and some ready to be executed.


OK, some of the other information is not shown.

conclusion

A GCRoot unreachable object will not be garbage collected immediately. First, we will judge whether Finalize method is included, and if so, finalize method will be executed first. If there are many such objects, then these objects will become useless even if GCRoot is unreachable, and they will remain in the memory, affecting the efficiency of the program.