Why Would You Ever Implement Finalize()

Why would you ever implement finalize()?

You could use it as a backstop for an object holding an external resource (socket, file, etc). Implement a close() method and document that it needs to be called.

Implement finalize() to do the close() processing if you detect it hasn't been done. Maybe with something dumped to stderr to point out that you're cleaning up after a buggy caller.

It provides extra safety in an exceptional/buggy situation. Not every caller is going to do the correct try {} finally {} stuff every time. Unfortunate, but true in most environments.

I agree that it's rarely needed. And as commenters point out, it comes with GC overhead. Only use if you need that "belt and suspenders" safety in a long-running app.

I see that as of Java 9, Object.finalize() is deprecated! They point us to java.lang.ref.Cleaner and java.lang.ref.PhantomReference as alternatives.

When is the finalize() method called in Java?

In general it's best not to rely on finalize() to do any cleaning up etc.

According to the Javadoc (which it would be worth reading), it is:

Called by the garbage collector on an object when garbage collection determines that there are no more references to the object.

As Joachim pointed out, this may never happen in the life of a program if the object is always accessible.

Also, the garbage collector is not guaranteed to run at any specific time. In general, what I'm trying to say is finalize() is probably not the best method to use in general unless there's something specific you need it for.

When should be we use finalize() method in java?

It is indeed preferable to release resources by calling a method explicitly. Finalizers are not necessarily called promptly or even at all. And they add a performance penalty.

However, finalizers may still be used as a safety net to release resources, in case the client has forgotten to dispose explicitly.

From the topic "Avoid finalizers" in Joshua Bloch's "Effective Java," 2nd ed.:

[D]on't use finalizers except as a safety net or to terminate noncritical
native resources. In those rare instances where you do use a finalizer,
remember to invoke super.finalize. If you use a finalizer as a safety net,
remember to log the invalid usage from the finalizer.

Good uses of the finalize() method

If your Java object uses JNI to instruct native code to allocate native memory, you need to use finalize to make sure it gets freed.

Why is the finalize() method deprecated in Java 9?

Although the question was asking about the Object.finalize method, the subject really is about the finalization mechanism as a whole. This mechanism includes not only the surface API Object.finalize, but it also includes specifications of the programming language about the life cycle of objects, and practical impact on garbage collector implementations in JVMs.

Much has been written about why finalization is difficult to use from the application's point of view. See the questions Why would you ever implement finalize()? and Should Java 9 Cleaner be preferred to finalization? and their answers. See also Effective Java, 3rd edition by Joshua Bloch, Item 8.

Briefly, some points about the problems associated with using finalizers are:

  • they are notoriously difficult to program correctly

  • in particular, they can be run unexpectedly when an object
    becomes unreachable unexpectedly (but correctly); for example,
    see my answer to this question

  • finalization can easily break subclass/superclass relationships

  • there is no ordering among finalizers

  • a given object's finalize method is invoked at most once by the JVM, even if that object is "resurrected"

  • there are no guarantees about timeliness of finalization or
    even that it will run at all

  • there is no explicit registration or deregistration mechanism

The above are difficulties with the use of finalization. Anyone who is considering using finalization should reconsider, given the above list of issues. But are these issues sufficient to deprecate finalization in the Java platform? There are several additional reasons explained in the sections below.

Finalization Potentially Makes Systems Fragile

Even if you write an object that uses finalization correctly, it can cause problems when your object is integrated into a larger system. Even if you don't use finalization at all, being integrated into a larger system, some parts of which use finalization, can result in problems. The general issue is that worker threads that create garbage need to be in balance with the garbage collector. If the garbage collector falls behind, at least some collectors can "stop the world" and do a full collection to catch up. Finalization complicates this interaction. Even if the garbage collector is keeping up with application threads, finalization can introduce bottlenecks and slow down the system, or it can cause delays in freeing resources that result in exhaustion of those resources. This is a systems problem. Even if the actual code that uses finalization is correct, problems can still occur in correctly programmed systems.

(Edit 2021-09-16: this question describes a problem where a system works fine under low load but fails under high load, likely because the relative rate of allocation outstrips the rate of finalization under high load.)

Finalization Contributes to Security Issues

The SEI CERT Oracle Coding Standard for Java has a rule MET12-J: Do not use finalizers. (Note, this is a site about secure coding.) In particular, it says

Improper use of finalizers can result in resurrection of garbage-collection-ready objects and result in denial-of-service vulnerabilities.

Oracle's Secure Coding Guidelines for Java SE is more explicit about potential security issues that can arise using finalization. In this case it is not a problem with code that uses finalization. Instead, finalization can be used by an attacker to attack sensitive code that hasn't properly defended itself. In particular, Guideline 7-3 / OBJECT-3 states in part,

Partially initialized instances of a non-final class can be accessed via a finalizer attack. The attacker overrides the protected finalize method in a subclass and attempts to create a new instance of that subclass. This attempt fails ... but the attacker simply ignores any exception and waits for the virtual machine to perform finalization on the partially initialized object. When that occurs the malicious finalize method implementation is invoked, giving the attacker access to this, a reference to the object being finalized. Although the object is only partially initialized, the attacker can still invoke methods on it....

Thus, the presence of the finalization mechanism in the platform imposes a burden on programmers who are trying to write high assurance code.

Finalization Adds Complexity to Specifications

The Java Platform is defined by several specifications, including specifications for the language, the virtual machine, and the class library APIs. Impact of finalization is spread thinly across all of these, but it repeatedly makes its presence felt. For example, finalization has a very subtle interaction with object creation (which is already complicated enough). Finalization also has appeared Java's public APIs, meaning that evolution of those APIs has (up to now) been required to remain compatible with previously specified behaviors. Evolving these specifications is made more costly the presence of finalization.

Finalization Adds Complexity to Implementations

This is mainly about garbage collectors. There are several garbage collection implementations, and all are required to pay the cost of implementing finalization. The implementations are quite good at minimizing the runtime overhead if finalization isn't used. However, the implementation still needs to be there, and it needs to be correct and well tested. This is an ongoing development and maintenance burden.

Summary

We've seen elsewhere that it's not recommended for programmers to use finalization. However, if something is not useful, it doesn't necessarily follow that it should be deprecated. The points above illustrate the fact that even if finalization isn't used, the mere presence of the mechanism in the platform imposes ongoing specification, development, and maintenance costs. Given the lack of usefulness of the mechanism and the costs it imposes, it makes sense to deprecate it. Eventually, getting rid of finalization will benefit everyone.

As of this writing (2019-06-04) there is no concrete plan to remove finalization from Java. However, it is certainly the intent to do so. We've deprecated the Object.finalize method, but have not marked it for removal. This is a formal recommendation that programmers stop using this mechanism. It's been known informally that finalization shouldn't be used, but of course it's necessary to take a formal step. In addition, certain finalize methods in library classes (for example, ZipFile.finalize) have been deprecated "for removal" which means that the finalization behavior of these classes may be removed from a future release. Eventually, we hope to disable finalization in the JVM (perhaps first optionally, and then later by default), and at some point in the future actually remove the finalization implementation from garbage collectors.

(Edit 2021-11-03: JEP 421 has just been posted, which proposes to deprecate finalization for removal. At this writing it's in the "candidate" state but I expect it will move forward. The deprecations added by this JEP are a formal notification that finalization will be removed at some point in a subsequent Java release. Perhaps not surprisingly, there's a fair overlap between the material in this answer and in the JEP, though the JEP is more precise and describes a moderate evolution in our thinking on the topic.)

(Edit 2022-04-04: JEP 421 Deprecate Finalization for Removal has been integrated and delivered in JDK 18.)

Is there any need for java's finalize method?

Backwards compatibility. Someone first thought it would be a good idea, and then when the world realized it was not such a great idea, it was too late.

These things are barely ever removed. Java is full of concepts that are considered bad idea nowadays but haven't been removed nevertheless - some more examples that come to my mind are clone() or Thread.stop().

Finalize vs Dispose

Others have already covered the difference between Dispose and Finalize (btw the Finalize method is still called a destructor in the language specification), so I'll just add a little about the scenarios where the Finalize method comes in handy.

Some types encapsulate disposable resources in a manner where it is easy to use and dispose of them in a single action. The general usage is often like this: open, read or write, close (Dispose). It fits very well with the using construct.

Others are a bit more difficult. WaitEventHandles for instances are not used like this as they are used to signal from one thread to another. The question then becomes who should call Dispose on these? As a safeguard types like these implement a Finalize method, which makes sure resources are disposed when the instance is no longer referenced by the application.

Why Netbeans warns me of finalize?

finalize methods have the problem that they may be called at an arbitrary time by an arbitrary thread or even never at all. And like discussed in this question they may be called surprisingly early, i.e. when instance methods are still being executed, so using them to free a resource is quite dangerous.

So if they are not really useful for what is their original purpose, it’s legitimate to always warn when you are using them.


If you want to implement code for cleaning up a resource, when client code has forgotten to call close or dispose or whatever you provide for explicit resource management (which you should if there are associated native resources) can be done using a PhantomReference to the instance and a ReferenceQueue.

The advantage is that you have control over when to poll the queue and perform the cleanup and you may even opt-out the post-mortem cleanup by letting the PhantomReference go out of scope (it will be ordinarily collected and not enqueued) in the case that the client code did not forget to call close (it’s strongly recommended to implemented AutoClosable to allow using “try with resources”). So this also solves the small performance issue that objects having a non-trivial finalize method must be collected twice as executing the finalize method implies that they become reachable again.

Why is finalize() only called once by garbage collector?

I don't know if its the original reason, but the current implementation enqueues Finalizer instances (internal subclass of Reference) for objects overriding the finalize method with an internal ReferenceQueue that gets polled by a dedicated FinalizerThread.

And because the JVM has no way of knowing whether the object would need to be finalized a second time it cannot decide whether it would have to enqueue a new Finalizer once the finalize() method has been called.

Anyway, you should avoid using finalize(). It makes object allocation more costly, prevents escape analysis and is not a very reliable way of managing native resources because the GC can postpone the finalization for an unbounded amount of time.



Related Topics



Leave a reply



Submit