RFR (s): 4354680: Runtime.runFinalization() silently clears interrupted flag in the calling thread

David Holmes david.holmes at oracle.com
Thu Oct 30 02:22:19 UTC 2014

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 = 
  152                 running = true;

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


> s'marks

More information about the core-libs-dev mailing list