Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clean up code in finalize() or finally()?

Tags:

java

I had the general view that clean up of resources is done in the finally block,
recently I found this particular code snippet in a class and it was overriding the Object class' finalize() method.

protected void finalize() {  
    try {
        In.close(); 
        Out.close();
        socket.close();
    }
    catch (Exception e) {
        //logger code here
    }
}

Is this a good idea? What are the pros and cons of finalize() over finally?

like image 399
Kevin Boyd Avatar asked Dec 03 '09 23:12

Kevin Boyd


4 Answers

The finally block is just a block of code that always executes after a try block, even if there is an exception. i.e. it is local in scope

The finalize() method is an approach for cleaning up the whole object when it is garbage collected.

Java documentation of finalize()

finally solves the problem of cleaning up resources in a block of code regardless of whether an exceptional condition occurs... finalize() is a way to clean up resources when your object is no longer being used, once the Garbage Collecter determines there are no more references to that object.

In short, to answer your question, for example, if the sockets you are closing are members of an object you should close them in the finalize() method, (although that's sub-optimal, and just for example, because there is no guarantee when the GC will actually perform the action)

If however you're opening the socket in a method, and are done with it when the method ends you should free the resources in the finally block.

like image 185
John Weldon Avatar answered Nov 01 '22 06:11

John Weldon


Always clean up things in finally.

Cleaning up in finalize is not guaranteed to occur.

However, it is often found to clean up such things in finalizers as a last-ditch safety valve should a finally block throw another exception on you.

The real problem with relying on finalizers is something else may need the resource before the GC gets around to calling the finalizer.

like image 25
Joshua Avatar answered Nov 01 '22 06:11

Joshua


Phantom References will do what you want.

Just don't use finalize. There are a few edge cases where it may be helpful (printing debug info when a class is GC'd has come in handy), but in general don't. There is nothing in the JVM contract that even says it ever has to be called.

There is a very under-publicized type of object called "References". One is made explicitly for things that you think you would use finalize for.

"Phantom reference objects, which are enqueued after the collector determines that their referents may otherwise be reclaimed."

It just occurred to me that there MUST be a description of this on the web--so I'll replace all the "how-to" stuff I just wrote with this reference.

like image 5
Bill K Avatar answered Nov 01 '22 04:11

Bill K


They're not related. This is like asking, "Should you create objects in an initializer or in normal methods?" Like, it depends on what you're doing with the objects. A finalizer cleans up an object's state while it's destroyed (maybe — it's not something you should rely on), while a finally block executes code after a try block. There isn't any common situation where you'd be able to choose one or the other since they do different things.

like image 4
Chuck Avatar answered Nov 01 '22 04:11

Chuck