JDK-4354680 : Runtime.runFinalization() silently clears interrupted flag in the calling thread
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 1.2.2,5.0,6,7,8,9
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: generic,linux,windows_nt
  • CPU: generic,x86
  • Submitted: 2000-07-19
  • Updated: 2019-05-22
  • Resolved: 2014-10-31
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7 JDK 8 JDK 9
7-poolUnresolved 8u162Fixed 9 b39Fixed
Description
Name: skT45625			Date: 07/19/2000


java version "1.2.2"
Classic VM (build JDK-1.2.2-004, native threads, symcjit)

If the thread which is already interrupted by another thread, calls
Runtime.getRuntime().runFinalization(), the interrupted status of the thread is
cleared (and API documentation doesn't say anything about it).
Sample code (my thread is already interrupted by another thread, before getting
here):

Runtime rt = Runtime.getRuntime();
System.out.println("Status: "+ Thread.currentThread().isInterrupted());
rt.runFinalization();
System.out.println("Status: "+ Thread.currentThread().isInterrupted());

will print to console:

Status: true
Status: false
(Review ID: 107365) 
======================================================================

Comments
Of course you are right Stuart. So all we lose is a little synchronicity.
30-10-2014

Looks to me like the secondary finalizer thread is started before the join() is interrupted, so if the method returns early, finalization has been triggered but might not yet have completed.
30-10-2014

The code currently returns from the join() immediately upon interrupt, so no change in behaviour there. I'm a little surprised no one has noticed that calling runFinalizers when the thread is interrupted doesn't trigger running of the finalizer. There are no guarantees of course but you could set up a simple test that would always work if the thread was not interrupted and failed if it was.
30-10-2014

I investigated this out of curiousity. (Which killed the cat, I know.) This traces down to java/lang/ref/Finalizer.java, in the forkSecondaryFinalizer() method. This code starts a new thread, and calls join() wrapped in a try/catch that simply ignores InterruptedException. If the interrupt bit was set upon entry to this method, join() will throw InterruptedException immediately, clearing the bit, and then IE is ignored. At the least, the catch block should reassert the interrupt bit. This might be insufficient, though, as runFinalization() would return early while finalization was still in progress. This might be an unacceptable behavior change. An alternative would be to query the interrupt bit before calling join(), and then repeatedly call join() until the thread really has exited, and then reassert the interrupt bit if either a) it was set initially, or b) InterruptedException was caught while joining the thread.
07-10-2014

The gc/gctests/FinalizeTest03 test has been excluded from the GC testing with JDK-8059761.
06-10-2014

Still happens in HS Nightly September 2014 See http://jdash.se.oracle.com/nightlies/bug/JDK-4354680
02-10-2014

WORK AROUND Name: skT45625 Date: 07/19/2000 Well, possibly: boolean interrupted = Thread.currentThread().isInterrupted() Runtime.getRuntime().runFinalization(); if (interrupted) Thread.currentThread().interrupt(); ======================================================================
11-06-2004