Finalizers is unpredictable, often dangerous, and generally unnecessary.
In Java, the GC automatically reclaims the space associated with an unreachable object without requiring the programmer to do the work.
For non-memory resources, we typically use the try-finally statement block for deallocation.
Finalizer does not guarantee immediate execution.
From an object programming unreachable state to calling finalizer, this time is arbitrary.
That is, time-sensitive operations cannot be performed in finalizer.
Never do anything time-critical in finalizer.
For example, some resource objects to Close,file descriptor is a limited resource, the consequences of not timely closure is very serious.
PS: autocloseable author is also Josh Bloch. )
Which finalizer will be implemented in a timely manner, this problem relies primarily on GC algorithms.
But the GC algorithm behaves more or less differently in different JVMs (the projects I've done are all using the hotspot ...).
A program might run well at development time, and a different environment might not work.
(for example, the finalizer priority is too low, has not been recycled, the recovery speed cannot keep up with the creation speed.) )
Not only does not guarantee the timeliness of finalizer execution, but also does not guarantee the possibility of finalizer execution.
Finalizer may not be executed at all.
For example, a lot of finalizer objects have not yet been executed, and the program is terminated.
Never depend on a finalizer to update critical persistent state.
Also do not expect the following methods to provide protection for the execution of finalizer:
System.gc();System.runFinalization();Runtime.runFinalizersOnExit(true);System.runFinalizersOnExit(true);
It is worth mentioning that if an uncaught exception is thrown in the finalizer, the exception is ignored and the stack trace is not printed.
In addition, finalizer has a very serious performance loss, which is best avoided as far as possible.
If an object encapsulates a resource (such as a file or a thread) that needs to be terminated, do not expect finalizer at this time.
Instead, it provides a display of the Close method (explicit termination), and joins a private domain that records the available state of the resource.
What is the point of finalizer?
-
When you forget to call the Close method, finalizer can be used as the last line of defense (safety net, or security net).
such as the Close method of FileInputStream and finalizer, when the private filedescriptor is not empty and does not belong to Java.lang.system#in, the Close method that is displayed is called:
/** * Ensures that the <code>close</code> method of this file input stream was * called when there a Re no more references to it. * * @exception IOException If an I/O error occurs. * @see java.io.fileinputstream#close () */protected void Finalize () throws IOException {if (FD! = null) &&A mp (FD! = filedescriptor.in)) {/* * Finalizer should not release the FileDescriptor if another * stream is still using it. If the user directly invokes * Close () Then the FileDescriptor is also released. */Runningfinalize.set (boolean.true); try {close (); } finally {Runningfinalize.set (boolean.false); } }}
Handles the local peer (native peer).
I didn't pay much attention to the term "local peer" before.
A local peer is a native object, and a normal object is delegated to a local object by a local method.
The GC cannot reclaim the local peer, and the local peer is not processed when the local peer's Java peer is recycled.
If the local peer does not have a critical resource (critical resource), finalizer can do the job.
PS: For the interpretation of local peers, refer to the following passage:
An AWT component is typically a component class that contains a reference to a peer interface type. This reference points to the local peer implementation.
Java.awt.Label, for example, its peer interface is labelpeer. Labelpeer is platform-independent.
On different platforms, AWT provides different peer classes to implement Labelpeer. On Windows, the peer class is Wlabelpeer, which invokes JNI to implement the label's functionality.
These JNI methods are written in C or C + +. They are associated with a local label, and the real behavior happens here.
As a whole, AWT components are provided by the AWT component class and AWT peers with a globally common API for application use.
A component class and its peer interface are platform-independent. The underlying peer class and JNI code are platform-dependent.
(an AWT component are usually a component class which holds a reference with a peer interface type. This reference points to a native peer implementation.
Take the Java.awt.Label for example, it peer interface is labelpeer.
Labelpeer is platform Independent. On every platform, AWT provides different peer class which implements Labelpeer. On Windows, the peer class was wlabelpeer, which implement label functionalities by JNI calls.
These JNI methods is coded in C or C + +. They do the actual work, interacting with a native label.
Let's look at the figure.
You can see this AWT components provide a universal public API to the application by AWT component class and AWT peers. A Component class and its peer interface is identical across platform. Those underlying peer classes and JNI codes are different. )
In addition, finalizer chaining was mentioned. The subclass constructor automatically calls the parent class constructor, so you might imagine that the subclass finalizer automatically calls the parent class finalizer. If the subclass finalizer the parent class, the subclass must manually invoke the Finalier of the parent class.
Effective Java-Avoid using finalizer