with - what is the purpose of finalization in java




Why would you ever implement finalize()? (14)

A simple rule: never use finalizers. The fact alone that an object has a finalizer (regardless what code it executes) is enough to cause considerable overhead for garbage collection.

From an article by Brian Goetz:

Objects with finalizers (those that have a non-trivial finalize() method) have significant overhead compared to objects without finalizers, and should be used sparingly. Finalizeable objects are both slower to allocate and slower to collect. At allocation time, the JVM must register any finalizeable objects with the garbage collector, and (at least in the HotSpot JVM implementation) finalizeable objects must follow a slower allocation path than most other objects. Similarly, finalizeable objects are slower to collect, too. It takes at least two garbage collection cycles (in the best case) before a finalizeable object can be reclaimed, and the garbage collector has to do extra work to invoke the finalizer. The result is more time spent allocating and collecting objects and more pressure on the garbage collector, because the memory used by unreachable finalizeable objects is retained longer. Combine that with the fact that finalizers are not guaranteed to run in any predictable timeframe, or even at all, and you can see that there are relatively few situations for which finalization is the right tool to use.

I've been reading through a lot of the rookie Java questions on finalize() and find it kind of bewildering that no one has really made it plain that finalize() is an unreliable way to clean up resources. I saw someone comment that they use it to clean up Connections, which is really scary since the only way to come as close to a guarantee that a Connection is closed is to implement try (catch) finally.

I was not schooled in CS, but I have been programming in Java professionally for close to a decade now and I have never seen anyone implement finalize() in a production system ever. This still doesn't mean that it doesn't have its uses, or that people I've worked with have been doing it right.

So my question is, what use cases are there for implementing finalize() that cannot be handled more reliably via another process or syntax within the language?

Please provided specific scenarios or your experience, simply repeating a Java text book, or finalize's intended use is not enough, and is not the intent of this question.


As a side note:

An object that overrides finalize() is treated specially by the garbage collector. Usually, an object is immediately destroyed during the collection cycle after the object is no longer in scope. However, finalizable objects are instead moved to a queue, where separate finalization threads will drain the queue and run the finalize() method on each object. Once the finalize() method terminates, the object will at last be ready for garbage collection in the next cycle.

finalize deprecated on java-9


Edit: Okay, it really doesn't work. I implemented it and thought if it fails sometimes that's ok for me but it did not even call the finalize method a single time.

I am not a professional programmer but in my program I have a case that I think to be an example of a good case of using finalize(), that is a cache that writes its content to disk before it is destroyed. Because it is not necessary that it is executed every time on destruction, it does only speed up my program, I hope that it i didn't do it wrong.

@Override
public void finalize()
{
    try {saveCache();} catch (Exception e)  {e.printStackTrace();}
}

public void saveCache() throws FileNotFoundException, IOException
{
    ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("temp/cache.tmp"));
    out.writeObject(cache);
}

Hmmm, I once used it to clean up objects that weren't being returned to an existing pool. They were passed around a lot, so it was impossible to tell when they could safely be returned to the pool. The problem was that it introduced a huge penalty during garbage collection that was far greater than any savings from pooling the objects. It was in production for about a month before I ripped out the whole pool, made everything dynamic and was done with it.


I'm not sure what you can make of this, but...

[email protected] ~/jdk1.6.0_02/src/
$ find . -name "*.java" | xargs grep "void finalize()" | wc -l
41

So I guess the Sun found some cases where (they think) it should be used.


I've been doing Java professionally since 1998, and I've never implemented finalize(). Not once.


Personally, I almost never use finalize() except in one rare circumstance: I made a custom generic-type collection, and I wrote a custom finalize() method that does the following:

public void finalize() throws Throwable {
    super.finalize();
    if (destructiveFinalize) {
        T item;
        for (int i = 0, l = length(); i < l; i++) {
            item = get(i);
            if (item == null) {
                continue;
            }
            if (item instanceof Window) {
                ((Window) get(i)).dispose();
            }
            if (item instanceof CompleteObject) {
                ((CompleteObject) get(i)).finalize();
            }
            set(i, null);
        }
    }
}

(CompleteObject is an interface I made that lets you specify that you've implemented rarely-implemented Object methods like #finalize(), #hashCode(), and #clone())

So, using a sister #setDestructivelyFinalizes(boolean) method, the program using my collection can (help) guarantee that destroying a reference to this collection also destroys references to its contents and disposes any windows that might keep the JVM alive unintentionally. I considered also stopping any threads, but that opened a whole new can of worms.


The accepted answer lists that closing a resource during finalize can be done.

However this answer shows that at least in java8 with the JIT compiler, you run into unexpected issues where sometimes the finalizer is called even before you finish reading from a stream maintained by your object.

So even in that situation calling finalize would not be recommended.


The resources (File, Socket, Stream etc.) need to be closed once we are done with their usage. They generally have close() method which we generally call in finally section of try-catch statements. Sometimes finalize() can also be used by few developers but IMO that is not a suitable way as there is no guarantee that finalize will be called always.

In Java 7 we have got try-with-resources statement which can be used like:

try (BufferedReader br = new BufferedReader(new FileReader(path))) {
  // Processing and other logic here.
} catch (Exception e) {
  // log exception
} finally {
  // Just in case we need to do some stuff here.
}

In the above example try-with-resource will automatically close the resource BufferedReader by invoking close() method. If we want we can also implement Closeable in our own classes and use it in similar way. IMO it seems more neat and simple to understand.


To highlight a point in the above answers: finalizers will be executed on the lone GC thread. I have heard of a major Sun demo where the developers added a small sleep to some finalizers and intentionally brought an otherwise fancy 3D demo to its knees.

Best to avoid, with possible exception of test-env diagnostics.

Eckel's Thinking in Java has a good section on this.


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.


You shouldn't depend on finalize() to clean up your resources for you. finalize() won't run until the class is garbage collected, if then. It's much better to explicitly free resources when you're done using them.


finalize() is a hint to the JVM that it might be nice to execute your code at an unspecified time. This is good when you want code to mysteriously fail to run.

Doing anything significant in finalizers (basically anything except logging) is also good in three situations:

  • you want to gamble that other finalized objects will still be in a state that the rest of your program considers valid.
  • you want to add lots of checking code to all the methods of all your classes that have a finalizer, to make sure they behave correctly after finalization.
  • you want to accidentally resurrect finalized objects, and spend a lot of time trying to figure out why they don't work, and/or why they don't get finalized when they are eventually released.

If you think you need finalize(), sometimes what you really want is a phantom reference (which in the example given could hold a hard reference to a connection used by its referand, and close it after the phantom reference has been queued). This also has the property that it may mysteriously never run, but at least it can't call methods on or resurrect finalized objects. So it's just right for situations where you don't absolutely need to close that connection cleanly, but you'd quite like to, and the clients of your class can't or won't call close themselves (which is actually fair enough - what's the point of having a garbage collector at all if you design interfaces that require a specific action be taken prior to collection? That just puts us back in the days of malloc/free.)

Other times you need the resource you think you're managing to be more robust. For example, why do you need to close that connection? It must ultimately be based on some kind of I/O provided by the system (socket, file, whatever), so why can't you rely on the system to close it for you when the lowest level of resource is gced? If the server at the other end absolutely requires you to close the connection cleanly rather than just dropping the socket, then what's going to happen when someone trips over the power cable of the machine your code is running on, or the intervening network goes out?

Disclaimer: I've worked on a JVM implementation in the past. I hate finalizers.


iirc - you can use finalize method as a means of implementing a pooling mechanism for expensive resources - so they don't get GC's too.





jvm