RedGrittyBrick said:
For releasing resources other than memory. The garbage collector only
collects memory. E.g. closing files, terminating network connections.
Not actually correct. Depending on 'finalize()' to release resources
is a recipe to fail to release resources. It is used for that only as
a court of last resort in case some client code fails to release
resources, and even then is usually a bad idea.
I've never needed to use finalize.
No one ever needs to use finalize() to release resources.
'finalize()', according to Joshua Bloch in his seminal /Effective
Java/, has two legitimate uses. One is as the aforementioned last
resort for when resources are not properly released, and not a very
good one there. The other is to coordinate with JNI code to release
memory on the native side when the Java object is reclaimed, if ever.
Read /Effective Java/ for why finalizers are otherwise a terrible
choice, and how to make them work properly in the rare cases when you
do need them.
I release resources using this pattern:
<obtain resource>
try {
<use resource>
} finally {
<release resource>
}
The other examples I've seen mentioned are when you use JNI to allocate
resources.
Well, Mr. Bloch points out that a "finalizer is an appropriate vehicle
for performing this task [releasing a native peer], /assuming the
native peer holds no critical resources/." (Emphasis original) In
other words, finalizers are not about releasing resources generally,
only memory.
Even when finalizers are appropriate, you have to be very, very
careful. A badly-written finalizer can hold huge object trees in
memory, potentially never to be reclaimed. You have to deliberately
limit the reach of a finalizer-laden class to avoid that flaw.