Before it reclaims storage from an object that is no longer referenced, the garbage collector calls finalize()
on the object.
But there is no guarantee that this method will be called as soon as the last references to the object are removed.
It can be few microseconds to few minutes later.
For this reason relying on overriding the finalize()
method to release resources or to update the state of the program is highly
discouraged.
What is the potential impact?
More unexpected issues can be caused by relying on the finalize()
method to perform important operations on the application state:
- The JVM might terminate without ever calling this method on a particular object, leaving an unexpected or incomplete state of the program
- Uncaught exceptions will be ignored inside this method, making it harder to detect issues that could have been logged otherwise
- Finalizer methods can also be invoked concurrently, even on single-threaded applications, making it hard to maintain desired program invariants
Noncompliant code example
public class MyClass {
@Override
protected void finalize() { // Noncompliant
releaseSomeResources();
}
}
Exceptions
It is allowed to override the finalize()
method as final
method with an empty body, to prevent the finalizer
attack as described in MET12-J-EX1.