Is there a destructor for Java? I don't seem to be able to find any documentation on this. If there isn't, how can I achieve the same effect?
To make my question more specific, I am writing an application that deals with data and the specification say that there should be a 'reset' button that brings the application back to its original just launched state. However, all data have to be 'live' unless the application is closed or reset button is pressed.
Being usually a C/C++ programmer, I thought this would be trivial to implement. (And hence I planned to implement it last.) I structured my program such that all the 'reset-able' objects would be in the same class so that I can just destroy all 'live' objects when a reset button is pressed.
I was thinking if all I did was just to dereference the data and wait for the garbage collector to collect them, wouldn't there be a memory leak if my user repeatedly entered data and pressed the reset button? I was also thinking since Java is quite mature as a language, there should be a way to prevent this from happening or gracefully tackle this.
I agree with most of the answers.
You should not depend fully on either
finalize
orShutdownHook
finalize
JVM does not guaranty when this
finalize()
method will be invoked.finalize()
gets called only once by GC thread if object revives itself from finalizing method than finalize will not be called again.In your application, you may have some live objects, on which garbage collection is never invoked.
Any Exception is thrown by finalizing method is ignored by GC thread
System.runFinalization(true)
andRuntime.getRuntime().runFinalization(true)
methods increase the probability of invokingfinalize()
method but now these two methods have been deprecated. These methods are very dangerous due to lack of thread safety and possible deadlock creation.shutdownHooks
The Java virtual machine shuts down in response to two kinds of events:
Shutdown hooks should also finish their work quickly. When a program invokes exit the expectation is that the virtual machine will promptly shut down and exit.
But even Oracle documentation quoted that
This occurs when the virtual machine is terminated externally, for example with the
SIGKILL
signal on Unix or theTerminateProcess
call on Microsoft Windows. The virtual machine may also abort if a native method goes awry by, for example, corrupting internal data structures or attempting to access nonexistent memory. If the virtual machine aborts then no guarantee can be made about whether or not any shutdown hooks will be run.Conclusion : use
try{} catch{} finally{}
blocks appropriately and release critical resources infinally(}
block. During release of resources infinally{}
block, catchException
andThrowable
.I fully agree to other answers, saying not to rely on the execution of finalize.
In addition to try-catch-finally blocks, you may use Runtime#addShutdownHook (introduced in Java 1.6) to perform final cleanups in your program.
That isn't the same as destructors are, but one may implement a shutdown hook having listener objects registered on which cleanup methods (close persistent database connections, remove file locks, and so on) can be invoked - things that would normally be done in destructors. Again - this is not a replacement for constructors but in some cases, you can approach the wanted functionality with this.
The advantage of this is having deconstruction behaviorloosely coupled from the rest of your program.
I am sorry if this strays from the main topic, but java.util.Timer (SE6) documentation says:
"After the last live reference to a Timer object goes away and all outstanding tasks have completed execution, the timer's task execution thread terminates gracefully (and becomes subject to garbage collection). However, this can take arbitrarily long to occur. By default, the task execution thread does not run as a daemon thread, so it is capable of keeping an application from terminating. If a caller wants to terminate a timer's task execution thread rapidly, the caller should invoke the timer's cancel method..."
I would like to call cancel upon the class owning the Timer losing its last reference(or immeditalesky before). Here a reliable destructor could do that for me. The comments above indicate that finally is a poor choice, but is there an elegant solution? That business of "...capable of keeping an application from terminating..." is not appealing.
Because Java is a garbage collected language you cannot predict when (or even if) an object will be destroyed. Hence there is no direct equivalent of a destructor.
There is an inherited method called
finalize
, but this is called entirely at the discretion of the garbage collector. So for classes that need to explicitly tidy up, the convention is to define a close method and use finalize only for sanity checking (i.e. if close has not been called do it now and log an error).There was a question that spawned in-depth discussion of finalize recently, so that should provide more depth if required...
If you use Java 7, have a look at the try-with-resources statement. For example:
Here the resource that is no longer needed is freed in the
BufferedReader.close()
method. You can create your own class that implementsAutoCloseable
and use it in a similar fashion.This statement is more limited than
finalize
in terms of code structuring, but at the same time it makes the code simpler to understand and maintain. Also, there is no guarantee that afinalize
method is called at all during the livetime of the application.Nope, no destructors here. The reason is that all Java objects are heap allocated and garbage collected. Without explicit deallocation (i.e. C++'s delete operator) there is no sensible way to implement real destructors.
Java does support finalizers, but they are meant to be used only as a safeguard for objects holding a handle to native resources like sockets, file handles, window handles, etc. When the garbage collector collects an object without a finalizer it simply marks the memory region as free and that's it. When the object has a finalizer, it's first copied into a temporary location (remember, we're garbage collecting here), then it's enqueued into a waiting-to-be-finalized queue and then a Finalizer thread polls the queue with very low priority and runs the finalizer.
When the application exits, the JVM stops without waiting for the pending objects to be finalized, so there practically no guarantees that your finalizers will ever run.