Hi Stuart,

You're a brave man! :)

On 30/10/2014 11:04 AM, Stuart Marks wrote:
Hi all,

Please review this small change that fixes this bug in
System.runFinalization() and Runtime.runFinalization().

Bug:     https://bugs.openjdk.java.net/browse/JDK-4354680

Webrev:  http://cr.openjdk.java.net/~smarks/reviews/4354680/webrev.0/

This is probably the simplest approach, which is to reassert the
interrupt bit if an InterruptedException is caught.

I'm slightly concerned by this, though, since if the join() was
interrupted (either because an interrupt was received while waiting to
join the thread, or the caller's interrupt bit was set at the time
join() was called), the method will return immediately, without waiting
for pending objects to be finalized. This seems to violate the spirit
(if not the letter) of this method's specification.

This is the way runFinalization() has always behaved, though. The only
difference with this change is that the interrupt bit is restored
instead of being cleared.

Right - there is no change in behaviour with your change other than fixing the problem with the cleared interrupt bit. That's the best you can do in my opinion.

One could imagine an alternative approach which would loop until the
secondary finalizer thread actually completes. However, it's hard for me
to imagine any code relying on runFinalization() synchronously clearing
the finalization queue. Since objects become finalizable asynchronously,
how would the caller know that the "right" set of objects had been
finalized? It seems to me that this isn't very useful, it's a change in
behavior, and it's harder to test.

The spec of this method is weak enough:

"When control returns from the method call, the virtual machine has made a best effort to complete all outstanding finalizations."

that nobody should have any expectations about what a single invocation of it should achieve. At best they might argue that the VMs "best effort" was pretty poor, but I can live with that - plus it would be a distinct RFE not part of this bug fix.

If we don't wait for the secondary finalizer thread to complete, perhaps
it would be appropriate to add a note to the doc about the early return
in case of an interrupt. Perhaps something like,

     If the calling thread is interrupted before or during this call,
     this call may return before all outstanding finalizations have been
     completed, and the calling thread's interrupt status will be set.

Would something like this be appropriate? Probably this would be added
to both System.runFinalization() and Runtime.runFinalization().

The fact a method is called that interacts with the interruption mechanism is purely an internal implementation detail. It should not bubble up to the specification of these methods. I don't see a need to document this aspect given the weakness of the spec as referenced above.

That said it may be worth doing a search for all tests that use runFinalization to see how it is used. If used in a loop (which I suspect is common) and the test is timing out and so the thread is interrupted by the test harness, it will become a spin loop.

Aside, I noticed in this code:

 146         forkSecondaryFinalizer(new Runnable() {
 147             private volatile boolean running;
 148             public void run() {
 149                 if (running)
 150                     return;
151 final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
 152                 running = true;

that as we create a new Runnable on every call, the "running" field serves absolutely no purpose.

Cheers,
David

s'marks

Reply via email to