Hi Stanimir, Andrew,

On 09/03/2014 01:48 PM, Stanimir Simeonoff wrote:
Hi Andrew,


On Wed, Sep 3, 2014 at 12:58 PM, Andrew Haley <a...@redhat.com> wrote:

On 03/09/14 01:15, Stanimir Simeonoff wrote:

Like David Lloyd mentioned finalize() can be invoked concurrently to
some methods (if there is no reachability to 'this'). OTOH I see
finalize useful for managing native resources mostly and possibly
stopping (signaling) threads left unmanaged. In that particular case
synchronization is a must, so it comes naturally.
But finalize isn't useful for managing native resources because
finalizers may or may not run, as you note.  People will test their
programs with one implementation then discover, when their programs
are deployed, that they sometimes mysteriously fail.  In particular,
you might run out of file handles.

Finalizers will eventually run, but they may not run on time. This could be fixed though (see below).


I meant cleaning up rather than managing per se. To make it clear:
finalization is no substitute for proper lifecycle - anything that has
open() should have a following up close(), otherwise it's a bug.
Finalization still helps as safenet vs leaving native resources totally
unallocated and leaking. Yet, finalizers have to run somehow since the
direct (and mapped) buffers very heavily rely on them.

DirectByteBuffers rely on Cleaner(s), which are PhanthomReferences and are managed (invoked) by the ReferenceHandler thread directly. Finalizers are just enqueued by ReferenceHandler thread, but they are invoked by the special FinalizerThread. That's because Cleaner(s) are internal JDK mechanism, while finalizers invoke client code so they can stall the FinalizerThread. A bug in a client code can bring FinalizerThread to a halt.

But there might be a cure for that at least for internal usage (for example: file handles)...

  The direct/mapped
buffers are ones that don't have proper lifecycle, esp. the mapped ones
The latter don't offer munmap.
I believe the java.nio.Bits still includes a notorious call in a

static void reserveMemory(long size, int cap) {
//check if above the direct memory threashold and...
         System.gc();
         try {
             Thread.sleep(100);
         } catch (InterruptedException x) {
             // Restore interrupt status
             Thread.currentThread().interrupt();
         }
}
in an attempt to cope with the lack of proper and timely finalization.
Prior the fix the OOM when using DirectBuffers was quite guaranteed unless
pooling the buffers on your own.
On a flip note, I think it's kind of a bug as it has to manually call run
System.runFinalization() prior throwing the OOM, but it opts to sleep 100ms
instead.

As said, DirectByteBuffer(s) use Cleaner(s), which are more predictable. But even with Cleaner(s), a multithreaded test could be constructed which reserves direct memory with greater rate than single ReferenceHandler thread can unreserve it. Until this was fixed:

https://bugs.openjdk.java.net/browse/JDK-6857566


An internal mechanism similar to that used in this patch could be devised for finalizers too. Allocation of native resources (like file handles) that are cleaned up by finalizers could use it to retry allocation if it fails, helping with cleanup on the way...

Peter


If the finalizers don't run prior the process termination, that's ok as the
OS should be able to clean up any native resources allocated on its own.
However finalizers not running is not that different from a weak/phantom
reference not being enqueued, practically the odds are quite the same. The
impl. of the finalization is actually a high priority dedicated thread that
processes a ReferenceQueue.



As Jarolsav put it, "I don't think this is explainable to regular Java
developers."  As David Lloyd put it, "If you still think that finalize
is a good idea, given that it's basically defective *and* there is
almost always a better solution, then I will be quite astounded."  As
I put it, "finalize is broken."


I'd not say "broken", as it works exactly as specified. Still I utterly
agree it requires pretty deep knowledge on the inner works to make it
somewhat useful.

Stanimir

Reply via email to