Re: Throwing Constructor Exceptions and cleaning up
Peter Duniho wrote:
A class can't decide after the fact whether to override finalize() or
not. It's part of the class definition. It can't conditionally
"un-override" the method if the client code correctly calls close(),
dispose(), etc.
That doesn't pose much of a problem in Java.
At the same time, a class that contains resources that Java can't
correctly clean up on its own really _must_ override finalize, to make
sure that buggy client code that fails to call close(), dispose(), etc.
The Java-idiomatic answer to that is not to write buggy code. If the
programmer takes the thought to write a 'finalize()' to do such things, they
shouldn't have done that; they should have written correct code "to call
close(), dispose(), etc." in the first place.
does not cause the entire system to fail (for example, file or network
i/o objects that retain references to expensive system resources that if
not correctly cleaned up eventually would result in the host system
exhausting those resources).
The advice in Java is, "Don't do that."
Assuming the client code uses the object correctly, and calls close(),
dispose(), etc. as required before it's done with the object, the
finalize() method won't have any real work to do. The cleanup will
already have happened.
And therefore one would not write a 'finalize()' method. Instead, one would
write correct code that "calls close(), dispose(), etc. as required before
it's done with the object".
The problem in Java with what you suggest is that there is not any guarantee
that an object will be GCed, ever, and if so, when, so if one has a critical
need to clean up resources, 'finalize()' is exactly the wrong place to rely on
to do it. The GC mechanism only tracks heap; it doesn't pay attention to what
other resources the program might waste.
The fact is, the need for a finalizer is the same in Java as for .NET,
and the opportunity to avoid calling the finalizer is the same in both.
No, it is not. The need in Java is to write a method other than a
'finalize()' override that does such things. The opportunity to avoid a
finalizer in Java is not to override 'finalize()' but to do such mandatory
tasks explicitly and not rely on GC to do it for you.
I know for a fact how .NET does it. Do you know for a fact how Java
does it? Or does not do it, as the case may be?
I do know for a fact what most JVMs do, in particular Sun's, which is that a
trivial (non-overridden) 'finalize()' is not actually run, but a non-trivial
finalizer is run during the first attempt to GC the object and actual
collection is deferred until the next attempt. It is that the JVM marks
non-trivially finalizable objects as such in order to know to do that. It is
that trivially finalizable objects only take one GC to clean up.
I suppose it is possible that there are JVMs that do otherwise. I'm mostly
familiar with the information pertaining to Sun's, not that I'm an expert.
What I've stated above is factual with respect to that.
--
Lew