Directory
Basic Preparation related knowledge
object's destruction process
An example of an object rebirth
The finalize execution order of the object
When and how to use Finalize
Reference
Basic Preparation related knowledge
1 Java GC is responsible only for memory-related cleanup, and all other resources must be cleaned by the programmer manually. Otherwise, it could cause a resource leak, which could cause the program to crash.
The 2 call GC does not guarantee the actual execution of the GC.
3 The not caught exception thrown by finalize will only cause finalize execution of the object to exit.
4 The user can call the Finalize method of the object himself, but this call is a normal method call and is independent of the object's destruction process.
5 The JVM guarantees that the method will be invoked if it implements the Finalize method before the memory occupied by an object is reclaimed. The default finalize for object does nothing, and for efficiency, the GC can assume that a finalize does not exist.
The 6 object's finalize call chain, like the clone call chain, must be constructed manually.
Such as
Java code protected void Finalize () throws Throwable {super.finalize (); }
object's destruction process
In the process of object destruction, according to the implementation of the object's finalize, can be divided into the following categories, the system will record the corresponding state of the object:
Unfinalized does not execute finalize and the system is not ready to execute.
Finalizable can execute finalize, and the system will execute finalize at a later time.
Finalized the object's finalize has been executed.
How does GC keep track of Finalizable objects? GC has a queue called F-queue, where all objects join the queue when they become finalizable, and then wait for the GC to execute its Finalize method.
At this point we introduced another record classification of objects, and the system can check which one object belongs to.
Reachable an object that can be reached from the active object reference chain. Includes local variables for all threads on the current stack, all static variables, and so on.
Finalizer-reachable except reachable, objects that can be reached by reference from F-queue.
Unreachable the other objects.
Look at the state transition diagram of the object.
So big, so dizzy, look slowly.
1 First, all the objects are from reachable+unfinalized to the road of death.
2 when the object is unreachable from the current active set, the object can be changed from the reachable state to the f-reachable or unreachable state.
3 When the object is reachable+unfinalized, the GC moves it into the f-queue, and the state changes to f-reachable+finalizable.
4 OK, the key is coming, at any time, GC can get a Finalizable object from F-queue, mark it as finalized, and then execute its Finalize method, because the object is reachable in this thread, The object then becomes reachable (and finalized). When the Finalize method executes, it is possible to turn other f-reachable objects into a reachable, which is called object regeneration.
5 When an object is unreachable+unfinalized, if the object uses the default object's finalize, or if it is overridden, the new implementation does nothing. For performance, GC can change the object to reclaimed state directly, without adding to the f-queue waiting for GC to do further processing.
6 see from the state diagram, no matter how toss, any object's finalize only executes at most once, once the object becomes finalized, how will not go back to f-queue. Of course, there is no chance to execute finalize again.
7 when an object is unreachable+finalized, the object is not far away from the real death. The GC can safely reclaim the object's memory. into the reclaimed.
An example of an object rebirth
Java code class c { static A a; } class a { B b; public a (b b) { this.b = b; } @Override public void finalize () { system.out.println ("A finalize"); C.a = this; } } class b { String name; int age; public b (String name, int age) { this.name = name; this.age = age; } @Override public void finalize () { System.out.println ("B finalize"); } @Override public string tostring () { return name + " is " + age; } } public class main { public static void main (String[] args) throws exception { a a = new a (new b ("Allen", 20)); a = null; system.gc (); thread.sleep (5000); system.out.println (c.a.b); } }
Expected output
Java code A finalize B. Finalize Allen is 20 but it may fail, stemming from GC uncertainty and timing problems, and several more times should be successful. Detailed explanation see the reference document at the end of the article.
The finalize execution order of the object
The finalize execution of all finalizable objects is indeterminate, not determining which thread is executing or the order of execution.
Consider the following situation to see why, the instance a,b,c is a set of finalizable objects that are circularly referenced by each other.
When and how to use Finalize
From the above analysis, to draw a conclusion.
1 most important, try not to use finalize, too complex, or let the system care better. Other methods can be defined to free a non-memory resource.
2 if used, try to be as simple as possible.
3 If use, avoid the object regeneration, this is oneself to find trouble.
4 can be used to protect a non-memory resource from being freed. Even if we define other methods to free a non-memory resource, others may not invoke the method to release it. In finalize it can be checked, if not released to release the Good, late release is better than not release.
5 You cannot guarantee that the object will be destroyed even if the object's finalize is already running. To implement some of the actions to ensure that objects are completely destroyed, you can only rely on the class and GC interactions within the JAVA.LANG.REF.
Reference
1. Author: zhang_xzhi_xjtu
URL: http://www.iteye.com/topic/484934
2, about reference types, Gc,finalize mutual interaction can refer to Referencequeue GC finalize Reference test and related issues