The dangers of the finalize method
When writing an article about using phantom links, I needed to refer to the inconvenience that occurs when working with the finalize method. In addition, I believe that this topic will be useful to all beginner java developers, and some experienced programmers will not be amiss to recall some points, because using the finalize method is very simple, which can not be said about finding the consequences of this. Even if you firmly believe never to use the finalize method, this does not mean that your previous colleagues did not use them, and you do not need to understand how they work.
So, let's go from the obvious to the less intuitive.
In accordance with the foregoing, the use of the finalize method should be avoided whenever possible, or rather, you should not rely on it. It is better to free resources programmatically, and to log in the finalize method, if for some reason this was not done, in order to find and fix the problem in time.
If, nevertheless, you need to free resources when assembling the object, then it is most likely better to use phantom links for this .
So, let's go from the obvious to the less intuitive.
- Since the finalize method is called during the first garbage collection following the moment when your object became unreachable, it is quite realistic that it will not be called at all, because your application can finish its work without reaching this garbage collection. Although, of course, there is one wonderful method System.runFinalizersOnExit (true) , calling which at the start of the program, the finalize method will still work for already unreachable objects during the correct application shutdown.
- The JVM specification does not address the issue of multithreading of the finalization method. In HotSpot, all finalize methods will be called sequentially in a single Finalizer thread. However, if you call the System.runFinalization () method , another thread will be born that will block the current one and will execute finalize methods if there are suitable objects in the queue. Moreover, this may well occur parallel to the main stream of Finalizer.
- Overriding the finalize method significantly lengthens the lifetime of the object after death, since it will not be deleted from memory until the second garbage collection. And given the first two points, if the finalize method is difficult for you and / or there will be a lot of such objects, then the objects can hang for a long time in the finalization phase and continue to occupy memory space.
- During the finalize method, you can restore the reference to the object, for example, placing it in some static context, thereby resurrecting the object. The danger of such a maneuver is that the second time the finalize method on this object will never be called. Therefore, if for some reason you really need to resurrect this object, it is better to create a copy inside the finalize method.
- One of the most annoying problems when using the finalize method is re-rendering. Imagine that you have two objects with an overridden finalize method, one of which references the other. So, if these objects become unattainable, then the order of calling the finalization methods will happen in random order. Thus, you will have the potential danger of calling some method on an already finalized object from the finalize method of another object and get an error. Moreover, the problem will not occur on every object, which will add a headache when debugging.
- According to Joshua Bloch, the author of the famous book “Effective Java: Programming Language Guide”, for objects with an overridden finalize method, allocation and assembly can be 430 times slower than with a regular object.
- Any exceptions thrown in the method body will be ignored.
- We must not forget at the end of the method to call super.finalize (). And given the previous paragraph, you need to do this in the finally block.
In accordance with the foregoing, the use of the finalize method should be avoided whenever possible, or rather, you should not rely on it. It is better to free resources programmatically, and to log in the finalize method, if for some reason this was not done, in order to find and fix the problem in time.
If, nevertheless, you need to free resources when assembling the object, then it is most likely better to use phantom links for this .