Java equivalents of malloc(), new, free() and deleteContinued from our introduction to memory management operators in C/C++ and Java. The delete operator in Java...?From the above, you'll have gathered that Java has no direct equivalent of delete. That is, there is no call that you can make to tell the JVM to "deallocate this object". It is up to the JVM to work out when an object is no longer referenced, and then deallocate the memory at its convenience. Now if you're a C++ programmer, at this point you might be thinking "that's cool, but what about deconstructors"? In C++, if a class has a deconstructor, it is called at the point of invoking delete and allows any cleanup operations to be carried out. In Java, things are slightly different:
An explicit deconstructor isn't needed in Java to deallocate "subobjects". In Java, if object A references object B, but nothing else does, then object B will also be eligible for automatic garbage collection at the same time as A. So there's no need for a finalizer (nor would it be possible to write one) to explicitly deallocate object B. Garbage collection and finalizationThe end of an object's life cycle in Java generally looks as follows:
You'll notice that there are a few "mays" and "arbitraries" in this description. In particular, there are a few implications that we need to be aware of if we use a finalizer:
So finalizers should really only be considered an "emergency" cleanup operation used on exceptional objects. A typical example is something like file stream or network socket. Although they provide a close() method, and we should generally try to use it, in the worst case, it's better than nothing to have the stream closed at some future point when the stream object goes out of scope. And we know that in the very worst case, the stream or socket will be closed when our application exits— at least on sensible operating systems3. This last point is important: the finalizer may not get called at all even in "normal" operation4, so it's really no good putting an operation in a finalizer whose execution is crucial to the system behaving once the application exits. Another typical use of a finalizer is for objects linked to some native code that allocates resources outside the JVM. The JVM can't automatically clean up or garbage collect such resources. How to create a finalizerSo despite all the warnings, if you still want to create a finalizer, then essantially you need to override the finalize() method of the given class. (Strictly speaking, every class otherwise inherits an empty finalize() method from Object, but good VMs can "optimise away" the default empty finalizer.) A typical finalizer looks as follows: protected void finalize() throws Throwable { super.finalize(); ... cleanup code, e.g. deleting a temporary file, calling a native deallocate() method etc... } General points about coding finalizers:
Alternatives to finalizersIn general, it's better to use an alternative to finalize() methods where possible— they really are a last resort. Safer alternatives include:
And of course, don't expect miracles. If the VM segfaults or there's a power cut5, there's no cleanup method or shutdown hook that's going to help you. If you are writing some critical application that requires "no data loss", you will have to take other steps (such as using a before-and-after transaction log) to minimise potential problems caused by abnormal shutdown.
1. It's not a terribly useful thing to do, but in principle you could "resurrect" an object during
the finalizer by creating a new reference to it. However, a finalizer is only ever called once;
once resurrected, the object will never be finalized again (though when all references
disappear again, it could be garbage collected). Written by Neil Coffey. Copyright © Javamex UK 2008. All rights reserved. |