1. The sequence

What this article means is that you should try not to overwrite finalize methods in your classes, and then write statements to free resources in your classes.

1.1 Why to avoid overwriting and using Finalize method?

  • (1) Finalize method cannot ensure that it can be executed in time.
  • (2) Finalize methods will not even be executed.
  • (3) System.gc and system. runFinalization can only increase the probability of finalize method being called.
  • (4) the only way to guarantee the finalize method is executed two, System. RunFinalizersOnExit and Runtime runFinalizersOnExit but these two methods have been deprecated.
  • (5) Overwriting and using finalization methods can cause serious performance losses.

1.2 What should we do if a resource in a class really needs to be freed?

Typically, the resources that need to be freed are threads or files and objects that refer to local resources.

All we need to do is provide a publicly decorated termination method that frees the resource, ask the user of the class to call the method when the class is no longer in use, and add a flag to the class to indicate whether the resource has been freed. If it has been freed, A method in this class throws an IllegalStateException if it is called. A good example is InputStream and OutputStream. By the way, it’s best to use the try — finally method when calling our own public decorated termination method, as follows:

class MyObject{ private boolean isClosed = false; Public void close(){public void close(){public void close(); isClosed = true; } } public static void main(String... args) { MyObject object = new MyObject(); Try {// Use object in this; . } finally {// Close object in this; object.close(); }}Copy the code

1.3 Destructor and termination method

Those of you who have studied C++ should immediately see finalizers and think of destructor in C++.

Finalizers in Java, like destructors in C++, are executed before the object is garbage collected, that is, before the object is destroyed.

In C++, destructors are often used to reclaim resources occupied by objects. However, due to the GC mechanism, there is no way in Java to predict when objects will be reclaimed, which means that we cannot predict when finalizing methods will be executed, and the Java language specification does not guarantee that finalizing methods will be executed. This is very dangerous.

Let’s demonstrate destructors and finalizers with the following example.

#include <iostream> using namespace std; class A { public: A(); // constructor, same as Java ~A(); // destructor, which is executed when the object is deleted}; A::A() {cout << "create object" << endl; } A::~A() {cout << "delete object" << endl; } int main() { A *a = new A(); delete a; Return 0; }Copy the code
Create an object Delete an objectCopy the code

Finalizers are often unpredictable, dangerous, and generally unnecessary. Using finalization methods can lead to erratic behavior, reduced performance, and portability issues.

2. Disadvantages of the termination method

Disadvantage of termination method 1:

Finalization methods are not guaranteed to be executed in a timely manner. The time between an object becoming unreachable and its finalizing method being executed is arbitrarily long. This means that time-critical tasks should not be done by finalization methods.

Disadvantages of termination method two:

If an uncaught exception is thrown during finalization, the exception can be ignored and the finalization of the object is terminated. Exceptions that are not caught leave the object in a corrupt state, and if another thread attempts to use the object, any undetermined behavior may occur. Normally uncaught exceptions cause the thread to terminate and print the stack trace, but if the exception occurs in a finalizing method, no warning is even printed!!

Disadvantages of termination method three:

Using the finalization method can result in a significant performance penalty. For example, creating and destroying a simple object on a machine takes about 5.6ns, and adding a finalization method increases to 2400ns.

3. Benefits of termination methods

Termination method first legal use:

Finalizing methods can act as a == “safety net” == when the object owner forgets to call the explicit termination method suggested earlier.

While this does not guarantee that the finalizing method will be executed in a timely manner, it is always better to release critical resources later in cases where the client == cannot explicitly call the finalizing method == to end the operation properly (a warning should be posted in the log if the finalizing method finds that the resource has not been terminated). Instances of explicit terminating methods (the four classes FileInputStream, FileOutputStream, Connection, and Timer) all have terminating methods that serve as a safety net when terminating methods don’t work.

The purpose of the “safety net” is to provide a safety net if the public decorated finalizer we provide is forgotten to be called externally, as follows:

class MyObject{ private boolean isClosed = false; Public void close(){public void close(){public void close(); isClosed = true; } @overried protected void finalize() throws Throwable {try{close(); } finally { super.finalize(); }}}Copy the code

The second advantage of the termination method

The second reasonable use of finalization methods has to do with the object’s native peer. A local peer is a native object. A common object is delegated to a local object by a local method. Since the local peer is not a common object, the garbage collection period does not know about it. Therefore, finalizing methods are the most appropriate tool for performing this task when the local peers do not have critical resources.

If the local peer has a resource that must be terminated in time, the class should have an explicit termination method. The termination method is to complete the necessary work and release critical resources. The terminating method can be a local method or it calls a local method.

Finalizers are also not automatically executed. If a class has a defined finalizer and its subclass overrides that finalizer, the subclass’s finalizer must manually call its parent class’s finalizer: To ensure that even if a subclass’s finalizing procedure throws an exception, the parent class’s finalizing method is executed (this also avoids common code attacks).

// Manual finalizer chaining @Override protected void finalize() throws Throwable { try { // Finalize subclass state } finally { super.finalize(); }}Copy the code

Another option is to use the Finalizer Guardian. If you want additional recommendations on this. Instead of enclosing a finalizing method in a class that requires finalization, you put it on an anonymous class whose sole purpose is to enclose its enclosing instance. A single instance of this anonymous class is called an finalizing method guardian.

If the subclass implementer overrides the superclass’s finalizing method, but forgets to call the superclass’s finalizing method, the superclass’s finalizing method is never called. To prevent this, you can use the finalizing method guardian, which creates an additional object for each object to be finalized. This additional object is an anonymous class instance, and puts the finalizing operations of the enclosing class, such as freeing resources, into the finalizing methods of that anonymous class. The enclosing instance keeps a unique reference to its finalizing method guardian in its private instance domain, so the finalizing method guardian and the enclosing instance can start the finalizing process at the same time. When the guardian is terminated, it performs the finalizing behavior expected by the enclosing instance as if its finalizing method were a method on the enclosing object.

Public class A {// finalizerGuardian private Final Object finalizerGuardian = new Object() {@override // finalizerGuardian methods are protected void finalize() { System.out.println("A finalize by the finalizerGuardian"); }}; Override // Since the finalizing method is overridden by a subclass, Protected void finalize() {system.out.println ("A finalize by the Finalize method"); } public static void main(String[] args) throws Exception { B b = new B(); b = null; System.gc(); Thread.sleep(500); } } class B extends A { @Override public void finalize() { System.out.println("B finalize by the finalize method"); }}Copy the code

Results:

1 A finalize by the finalizerGuardian
2 B finalize by the finalize method
Copy the code

4. To summarize

In summary, do not use finalization methods unless you are using them as a safety net or to terminate non-critical local resources.

  • 1. In the rare cases where finalization is used, super.Finalize should be used.
  • 2. If used as a safety net, remember to record illegal uses of finalization methods.
  • 3. If you need to associate a finalizing method with a public non-final class, consider using a finalizing method guardian to ensure that a finalizing method of a subclass will be executed even if it does not call super.Finalize.

5. References

www.jianshu.com/p/bc96028e0… My.oschina.net/u/4689327/b…

Pay attention to the public account “Programmer interview”

Reply to “interview” to get interview package!!

This public account to share their own from programmer xiao Bai to experience spring recruitment autumn recruitment cut more than 10 offer interview written test experience, including [Java], [operating system], [computer network], [design mode], [data structure and algorithm], [Dacheng face by], [database] look forward to you join!!

1. Computer network —- Three times shake hands four times wave hands

2. Dream come true —– Project self-introduction

Here are the design patterns you asked for

4. Shocked! Check out this programmer interview manual!!

5. Teach you the interview “Profile” word for word

6. Nearly 30 interviews shared

7. Here are the free books you asked for