JDK-4992463 : ClassLoading fails if the Thread's interrupt status is set
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 5.0
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2004-02-11
  • Updated: 2017-07-20
  • Resolved: 2017-07-20
Related Reports
Relates :  
Relates :  
Relates :  
Description
Name: gm110360			Date: 02/10/2004


FULL PRODUCT VERSION :
java version "1.5.0-beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta-b32c)
Java HotSpot(TM) Client VM (build 1.5.0-beta-b32c, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows 2000 [Version 5.00.2195]

A DESCRIPTION OF THE PROBLEM :
If multiple threads are performing certain security or JCE operations simultaneously (e.g. generating key pairs), and if one or more of those threads is in the "interrupted" state, then an InterruptedException is thrown. I have encountered this behavior intermittently while performing encryption using the JCE (in a test server application), and also while generating key pairs (in the example program below). I'm not sure if this behavior is limited to calling security/JCE methods or not.

I should not be receiving an InterruptedException, because it is a checked exception, and is not declared to be thrown from the security/JCE methods that I am calling. Furthermore, the stack trace seems to be incorrect, and it varies between different Java versions and different test machines.

I'm unware of any documentation indicating that it is dangerous to leave a thread in the interrupted state while that thread is calling Java API methods. If it is indeed dangerous to do so, I feel that this should be clearly indicated in the Java thread documentation/tutorial.

The following link contains a discussion between developers regarding this problem:

http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&threadm=84544f8d.0312022135.4658490f%40posting.google.com&rnum=2

Note: I also experience similiar behavior running the test program using the BouncyCastle security provider with Java 1.1

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the attached program.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I expect to see the message "Keys successfully generated" 5 times.
ACTUAL -
I receive the message "Keys successfully generated" once, and 4 InterruptedExceptions.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
When compiled/run with Java 1.5.0:

java.lang.InterruptedException
        at sun.security.jca.GetInstance.getServices(GetInstance.java:96)
        at java.security.KeyPairGenerator.getInstance(KeyPairGenerator.java:165)
        at GenerateKeyTest.run(GenerateKeyTest.java:11)

When compiled/run with Java 1.4.2:

java.lang.InterruptedException
        at sun.security.provider.SecureRandom.engineNextBytes
SecureRandom.java: 168)
        at java.security.SecureRandom.nextBytes(SecureRandom.java:381)
        at COM.rsa.jsafe.SunJSSE_eq.a(DashoA6275)
        at COM.rsa.jsafe.SunJSSE_df.c(DashoA6275)
        at com.sun.net.ssl.internal.ssl.JS_KeyPairGenerator.generateKeyPair(Dash
oA6275)
        at java.security.KeyPairGenerator$Delegate.generateKeyPair(KeyPairGenerator.java:475)
        at GenerateKeyTest.run(GenerateKeyTest.java:13)


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.security.KeyPairGenerator;

public class GenerateKeyTest extends Thread
{
  public void run()
  {
    try
    {
      interrupt(); // Comment out this line and it works OK
      System.out.println("About to generate keys");
      KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
      kpg.initialize(1024);
      kpg.generateKeyPair();
      System.out.println("Keys successfully generated");
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
  }

  public static void main(String[] args)
  {
    for (int i = 0; i < 5; i++)
      new GenerateKeyTest().start();
  }
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
The workaround is to ensure that you never interrupt() a thread while it is calling any methods in the security classes (and possibly other Java API classes as well). This can be achieved with synchronization.
(Incident Review ID: 238237) 
======================================================================

Comments
There hasn't been any activity on this issue since 2006 so I'm closing this issue. Interruptible I/O has been removed from Solaris for several releases so it should not be an issue. Also this bug report was Windows. Re-open or create a new issue if there are recent reports on this issue.
20-07-2017

EVALUATION See CR 4329256 for an explanation of the "missing print output", which is an issue that is separate both from thread interruption interferring with class loading and the issue of "InternalError noise" emanating from classes_security. It's better to leave this CR as a still-open overlap with CR 6375934 and file a separate CR to document the latter issue. It turns out that the original test case of this current CR is excellent for reproducing one of the still remaining problems with interrupted class loading (if it is run with a "developent classes directory" instead of "from rt.jar of shipped binaries").
01-05-2006

EVALUATION The TestInterrupt program above, which has nothing to do with security, still does not work on Mustang-b82, at least not on solaris-i586. It is supposed to print the two lines "C1 OK" and "OK" but instead it terminates without printing anything and without an exception: === % java -showversion TestInterrupt java version "1.6.0-beta2" Java(TM) SE Runtime Environment (build 1.6.0-beta2-b82) Java HotSpot(TM) Server VM (build 1.6.0-beta2-b82, mixed mode) % === Transferring back to classes_lang.
28-04-2006

EVALUATION (Realizing the switch back to classes_security might make folks wonder what is going on.) This was shifted back to classes_security because the underlying problem is avoided with the suggested fix for 4764778, but with that suggested fix there is "noise" before the keys are generated that is caused by security code not expecting an exception.
23-12-2005

EVALUATION I believe this is an unavoidable consequence of how synchronization and thread interruption works in Java. Will check with someone who knows for sure. ###@###.### 2004-02-11 What this comes down to appears to be this: === public class TestInterrupt { public static void main(String[] args) throws Exception { // interrupt myself, this will set interrupt status Thread.currentThread().interrupt(); // access class C1. this triggers I/O for classloading, // which is immediately interrupted due the interrupt status // class loading fails, triggering a NoClassDefFoundError // alternatively, uncomment the Class.forName() call, // which prints the original Exception // Class.forName("TestInterrupt$C1"); C1.print(); System.out.println("OK"); } private static class C1 { static void print() { System.out.println("C1 OK"); } } } === If the interrupt status of a Thread is set, all classloading will fail. As calling any method can directly or indirectly cause classloading, a program can fail in a random way. The reason this usually is not observed is that Thread.interrupt() calls are usually only made once the relevant classes have already been loaded. It would seem better if classloading would ignore the interrupt status, but that is for the classloading team to decide. Transferring to classes_lang. ###@###.### 2005-05-18 01:08:52 GMT
18-05-2005