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

Stuart Marks stuart.marks at oracle.com
Thu Oct 30 05:40:15 UTC 2014

On 10/29/14 7:22 PM, David Holmes wrote:
> Hi Stuart,
> You're a brave man! :)


> 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.

OK, after thinking about it, I was starting to lean that direction too.

> 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.


> 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.

Fair enough. Less work. :-)

> 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.

Yes, I've started to look at some of the uses of runFinalization(). Mostly in 
tests so far, but I haven't looked everywhere yet. Most uses seem to call some 
combination of System.gc() and System.runFinalization(), and then sleep for a 
while, so there is implicitly some notion of waiting for finalization to occur 
asynchronously. Or, they have the finalizer set some piece of state that's 
waited for.

If such a test were to time out (and interrupt the thread) during a call to 
runFinalization(), the change would preserve the interrupt bit instead of 
clearing it. But most such tests have code like,

     try { Thread.sleep(DELAY); } catch (InterruptedException ignore) { }

so the interrupt would get ignored anyway....

(Yet Another Cleanup Task: fix all the tests that ignore InterruptedException.)

> 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.

Ha. Good catch. This was probably refactored from a static field of a containing 
class. The intent was probably to prevent multiple secondary finalizer threads 
from running, but it wouldn't do this very well even if it were static.

I'll clean this up since it clearly serves no purpose as it stands.



More information about the core-libs-dev mailing list