Before explaining the use of finalize (), there are a few points to be set about the Java garbage collector:
- "Object can not be garbage collected": Java garbage collection follows a feature, that is, can not be recycled without recycling. As long as the program's memory does not reach the point where it will be exhausted, the space occupied by the object will not be released. Because if the program ends properly and the garbage collector does not release the requested memory, Then with the normal exit of the program, the requested memory will be automatically returned to the operating system; and garbage collection itself has to pay a price, there is a certain cost, if not used, there will be no cost of this part.
- Garbage collection can only reclaim memory, and it can only reclaim part of memory that is consumed by objects created by Java-created objects (heaps), and cannot reclaim other resources, such as handles to file operations, database connections, and so on.
- Garbage collection is not a destructor in C + +. The two are not correspondence, because the 1th point is that the occurrence of garbage collection is indeterminate, while the destructor in C + + occurs when the programmer controls (delete) or the departure scope, which destroys the object at a determined time and frees the memory it occupies.
- Calling the garbage collector (GC) does not necessarily guarantee that the garbage collector runs
Finalize () function: Once the garbage collector is ready to release the memory space occupied by the object, if the object overrides Finalize () and the function body cannot be empty, the object's Finalize () is called first. Then, when the next garbage collection action occurs, it really reclaims the space occupied by the object.
One feature of Finalize () is that the JVM is always called only once. Finalize () is always called only once, regardless of the state that the object is flagged by the garbage collector. But the programmer's active invocation in code is not recorded in this.
If you need to dispose of the resources of the object's parent class, you must manually construct the finalize call chain yourself
protected void Finalize () throws Throwable { super.finalize (); }
The main uses of Finalize ():
- According to the 2nd of the garbage collector, the Java garbage collector can only reclaim Java objects that are created in the heap, and there is no method processing for objects that are not created in this way, which requires the use of finalize () to dispose of the resources that this part of the object occupies. The use of this is the JNI local object, the object created by JNI to invoke the local method can only be destroyed by using Finalize (), freeing the memory
- Act as the last barrier to releasing resources after use, such as after using a database connection, and forgetting to release a connection because of a programmer's personal reasons, you can only rely on the Finalize () function to release resources.
- Thinking in Java, "termination condition" validation, using the Finalize () method to try to identify a program's vulnerability
Although finalize () can be invoked proactively, it is best not to invoke it proactively, because after the active invocation in code, if the JVM is called again, because the previous call has already freed the resource, it is possible to release the resources two times to cause exceptions such as null pointers, which are not captured. This causes the object to be in a corrupted state, causing the object to consume a portion of the resource that cannot be recycled.
Try to avoid using Finalize ():
- Finalize () is not necessarily called because the Java garbage collector's nature determines that it is not necessarily called
- Even if the Finalize () function is called, the time it is called is fraught with uncertainty because the other threads in the program have a much higher priority than the execution of the Finalize () function thread. Perhaps until finalize () is called, the connection pool or file handle for the database is already exhausted.
- If an uncaught exception is thrown when the Finalize method is used, the exception is not captured, and the finalization process terminates, causing the object to be in a state of destruction. The objects that are destroyed are likely to cause some resources not to be recycled, resulting in waste.
- Finalize () and the garbage collector run on their own resources, which may cause the program to stop temporarily.
Finalize the life cycle of the execution:
- Finalize process: When an object becomes (GC Roots) Unreachable, the GC determines whether the object overrides the Finalize method, and if it is not overwritten, it is recycled directly. Otherwise, if the object does not perform a Finalize method, it is placed in the F-queue queue, and a low-priority thread executes the Finalize method of the object in that queue. After the Finalize method is executed, the GC will again determine whether the object is reachable or not, and if not, the object is "resurrected" if it is not reachable.
- objects can be composed of two states, involving two types of state space, one is the final state space F = {unfinalized, finalizable, finalized}, and the second is the state space R = {reachable, finalizer-reachable, Unreachable}.
- UNFINALIZED:GC does not call the object's Finalize (), nor does it prepare to invoke the object's Finalize ().
- Finalizable: Represents the GC callable object's Finalize (), but has not yet called
- Finalized: Indicates that the GC has called the Finalize () of the object
- Reachable: Represents a GC roots reference, such as a variable in the stack that refers to the object
- Finalizer-reachable (f-reachable): Indicates not reachable, but can be reached by a Finalizable object
- Unreachable: Objects can not be reached through the above two ways, that is, unreachable, no object reference.
- Status Change chart:
- Specific state transitions:
- New object First in [reachable, unfinalized] State (A)
- As the program runs, some referential relationships disappear, resulting in state transitions from reachable state to F-reachable (B, C, D) or unreachable (E, F) states
- If the JVM detects that an object in the unfinalized state becomes f-reachable or UNREACHABLE,JVM marks it as a finalizable state (g,h). If the object is originally in the [Unreachable, unfinalized] state, it is also marked as f-reachable (H).
- At some point, the JVM takes out a finalizable object, marks it as finalized, and executes its Finalize method in a thread. Because the object is referenced in the active thread, the object changes to the (reachable, finalized) state (K or J). This action will affect some other objects from the f-reachable state back to the reachable state (L, M, N), which is the object rebirth
- An object in the finalizable state cannot be unreahable at the same time, and by the 4th, the Finalizable object is marked as finalized by a thread that executes the Finalize method of the object, causing it to become reachable. That's why there are only eight status points in the diagram.
- The programmer's Manual call to the Finalize method does not affect the changes in the internal tags above, so the JVM will only call finalize once, even if the object is "resurrected". How many times the programmer manually calls does not affect the behavior of the JVM
- If the JVM detects that the finalized state object becomes unreachable, reclaims its memory (I)
- If the object does not overwrite the Finalize method, the JVM optimizes and reclaims the object directly (O)
Note: the System.runfinalizersonexit () method allows the JVM to perform a Finalize method on the object even if it is in the reachable state
Code 1 for Object rebirth:
Class C { static 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"));
a = null; System.GC (); Thread.Sleep (the); System.out.println (C.A.B); } }
My understanding: For the sake of convenience, the memory space referred to by a A, a, two variable is called A and b
- A = new A (New B ("Allen", 20)); At this point A and B are reachable, unfinalized state
- A = null;
- After that, the status of a and B becomes unreachable at some point, unfinalized (but B becomes unreachable or f-reachable I'm not sure if you know, welcome to add ^_^)
- Or A and b directly into F-reachable, unfianlized.
- Then at some point, the GC detects that A and B are in the unfinalized state, adds them to the f-queue, and changes the status to F-reachable finalizable.
- There are two different situations:
- First: The GC first takes a from F-queue and is executed by a thread by a finalize (), which is equivalent to being held by an active thread, and a state becomes reachable, finalized. At this point, because a is referenced by the C object, it does not become unreachable finalized and is destroyed (reborn) at the same time, B has been quoted by a, so the state of B becomes reachable, finalizable. And then, at some point, it's taken out from F-queue, into reachable, finalized state.
- Second: The GC first takes out B from the F-queue and is executed by a thread with Finalize (), and the state becomes reachable finalized. Then a is similar, becomes reachable finalized state, and is referenced by C, reborn
Code 2 for Object rebirth:
public class gc{public static GC save_hook = null; public static void Main (string[] args) throws Interruptedexception, Throwable { save_hook = new GC (); Save_hook = null; System.GC (); Thread.Sleep (+); if (null! = Save_hook) //At this time the object should be in the (reachable, finalized) state { System.out.println ("Yes, I am still Alive"); c11/>} Else { System.out.println ("No, I am Dead"); } Save_hook = null; System.GC (); Thread.Sleep (+); if (null! = Save_hook) { System.out.println ("Yes, I am still Alive"); } else { System.out.println ("No, I am Dead"); } } @Override protected void Finalize () throws Throwable { super.finalize (); System.out.println ("Execute Method Finalize ()"); Save_hook = this; }}
Data from: http://blog.csdn.net/rsljdkt/article/details/12242007#; http://blog.sina.com.cn/s/blog_66a6172c01018jda.html; http://zhang-xzhi-xjtu.iteye.com/blog/484934
"Thingking in Java" note. If there's something wrong, welcome to ^_^.
The Finalize () function of Java