Transfer from http://www.threaddeath.com/
Wandering Iteye saw a translation blog of the translation of the emperor, which referred to the Java class rewrite the Finalize method after the bizarre GC overhead limit problem. The end of the blog is a very detailed explanation of the principle of the problem, but there is always a place where there is no clear answer: Because the Finalize method is the protected method of the Object class, whether it is rewritten or not, All Java classes will have a Finalize method, but why is there a GC problem only after rewriting, and what is the real difference between rewriting and rewriting?
Never get the answer by thinking, just open Eclipse Direct debugging code:
- First, verify that the phenomenon in the blog can indeed be reproduced.
- One of the problems that was suspected in the middle is that the static variable Atomicinteger the class in the Finalize method can cause problems with the GC (in fact this direction is wrong, and the GC determines whether the object is recycled or ashamed depending on whether the object has a referenced relationship), Delete the original method body and then arbitrarily declare a variable in the Finalize method, the result of the run-time problem still exists.
- At this point, began to doubt whether it is related to the Finalize method body, directly delete all the contents of the Finalize method body, after the operation found that the problem really does not exist!
- Since a large number of finalizer objects exist in the memory heap when GC problems occur, and the finalizer object can only be created by the static Register method of the finalizer class, attempting to add a breakpoint to the Register method to run the two cases, and to find that the method body is empty, The Register method is not invoked so that the custom object is not referenced by any object and can be easily reclaimed by GC.
- Since the Register method is called by the VM and can only resort to Mo Shi, Mo Shi also confirms that as long as the Java class and all its ancestor classes do not contain a Finalize method or the Finalize method body is empty, The VM does not register an object instance of the class as a Finalizable object (address).
At this point, it is the whole question of the context of the collation of almost:
- The JVM creates a custom object.
- The JVM detects whether the object class and ancestor classes contain non-empty finalize method definitions, and if none, does not carry out subsequent finalizer related processing.
- The JVM invokes the static register method of the finalizer class, creates a finalizer object that contains the object reference, and finalizer a static class to add the finalizer object to a one-way linked list.
- During the run, the JVM updates the status of these finalizer objects to pending (This section can refer to the instructions in the Java.lang.ref.Reference Class).
- Referencehandler threads in the reference class scan to these finalizer objects that have a status of pending. These objects are enqueue to the referencequeue of finalizer static class references (non-finalizer, a one-way linked list).
- The finalizer thread pops the finalizer object from the Referencequeue, first removing the finalizer object from the finalizer one-way list, releasing the finalizer static class's reference to the finalizer object, The Finalize method of the custom object referenced by the finalizer object is then called, and both the finalizer object and the custom object can be reclaimed by GC at this time.
- Due to the low priority of the finalizer thread, it may cause the old object to be released faster than the new object is created, causing outofmemory problems (GC overhead in the example The limit is due to the fact that the cost of new object creation is too low for objects to be recycled more than 98% of the time the CPU uses for GC recycling.
Finally, the NetEase Research Institute's Ma Jin in his blog in very detailed elaboration of the principle of finalize and so the case, it is also worth reading.
Finalize method vs. Java GC