Valid Java, inclutivejava
Finalizers are unpredictable ,often dangerous ,and generally unnecessary.
In Java, GC automatically recycles space related to inaccessible objects, without the need for programmers to do relevant work.
For non-memory resources, we usually use try-finally statement blocks for release.
Finalizer does not guarantee immediate execution.
From the inaccessibility of an object programming to the call of finalizer, this time is arbitrary.
That is, time-sensitive operations cannot be performed in finalizer.
never do anything time-critical in finalizer.
For example, to close some resource objects, file descriptor is a limited resource, and the consequence of not closing it in time is very serious.
(PS: the author of AutoCloseable is also Josh Bloch .)
Which finalizer will be executed in a timely manner? This problem mainly depends on the GC algorithm.
However, GC algorithms may behave more or less differently in different JVMs (I have used Hotspot for all projects I have done ...).
A program may run well during development, but changing the environment may fail to run normally.
(For example, the priority of finalizer is too low and it has never been recycled. The collection 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, if the finalizer of many inaccessible objects has not been executed, the program is terminated.
Never depend on a finalizer to update critical persistent state.
Do not expect the following methods to guarantee the execution of finalizer:
System.gc();System.runFinalization();Runtime.runFinalizersOnExit(true);System.runFinalizersOnExit(true);
It is worth mentioning that if an uncaptured exception is thrown in finalizer, the exception will be ignored and even the stack trace will not be printed.
In addition, finalizer has very serious performance loss, which should be avoided as much as possible.
If the resources encapsulated by an object (such as files or threads) need to be terminated, do not expect finalizer.
Instead, an explicit close method is provided and added to a private domain that records the available status of the resource.
So what is the significance of finalizer?
-
When you forget to call the close method, finalizer can be used as the final line of defense (safety net, namely the security net ).
For example, the close method and finalizer method of FileInputStream are called when the private FileDescriptor is not empty and does not belong to java. lang. System # in:
/** * Ensures that the <code>close</code> method of this file input stream is * called when there are 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) && (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); } }}
-
Native peer ).
I didn't pay too much attention to the word "local peer.
A local peer is a native object. A common object is delegated to a local object through a local method.
GC cannot recycle the local peer. When the java Peer of the local peer is recycled, the local peer is not processed.
If the local peer does not need a critical resource, finalizer can do the job.
PS: For an explanation of the local peer, refer to the following section:
An AWT component is usually a component class that contains the reference of the peer interface type. This reference points to the local peer implementation.
Java. awt. Label is used as an example. Its peer interface is LabelPeer. LabelPeer is platform independent.
On different platforms, AWT provides different peer classes to implement LabelPeer. In Windows, the peer class is WlabelPeer, which calls JNI to implement the label function.
These JNI methods are written in C or C ++. They are associated with a local label, and the actual behavior occurs here.
As a whole, the AWT component provides a global public API for the application by the AWT component class and the AWT peer.
A component class has nothing to do with its peer interface. The underlying peer classes and JNI code are platform-related.
(An AWT component is usually a component class which holds a reference with a peer interface type. This reference points to a native peer implementation.
Take java. awt. Label for example, its peer interface is LabelPeer.
LabelPeer is platform independent. On every platform, AWT provides different peer class which implements LabelPeer. On Windows, the peer class is WlabelPeer, which implement label functionalities by jni cils.
These JNI methods are coded in C or C ++. They do the actual work, interacting with a native label.
Let's look at the figure.
You can see that AWT components provide a universal public API to the application by AWT component class and AWT peers. A component class and its peer interface are identical internal SS platform. those underlying peer classes and JNI codes are different .)
In addition, we mentioned finalizer chaining. The subclass constructor automatically calls the parent class constructor, so it may be imagined that the subclass finalizer automatically calls the parent class finalizer. If the subclass rewrites the finalizer of the parent class, the subclass must manually call the finalier of the parent class.