1

The error: on the ssl handshake with the ssl server. After: client hello, server hello, certificate, server key exchange and server hello done. The web apps crashes with: java.lang.NoClassDefFoundError: Could not initialize class javax.crypto.SunJCE_b

The problem occurs on:
tomcat 6.0.29

Tried the following JVM:
1.5, 1.6_22, 1.6_25
now running:
java -version java version "1.6.0_25" Java(TM) SE Runtime Environment (build 1.6.0_25-b06) Java HotSpot(TM) Server VM (build 20.0-b11, mixed mode)

Operating System:
uname -a
SunOS hostname 5.10 Generic_118833-33 sun4v sparc sun4v

More details:

The stacktrace:

java.lang.NoClassDefFoundError: Could not initialize class javax.crypto.SunJCE_b
    javax.crypto.KeyGenerator.a(DashoA13*..)
javax.crypto.KeyGenerator.<init>(DashoA13*..)
javax.crypto.KeyGenerator.getInstance(DashoA13*..)
com.sun.net.ssl.internal.ssl.JsseJce.getKeyGenerator(JsseJce.java:223)
com.sun.net.ssl.internal.ssl.RSAClientKeyExchange.<init>(RSAClientKeyExchange.java:89)
com.sun.net.ssl.internal.ssl.ClientHandshaker.serverHelloDone(ClientHandshaker.java:744)
com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:238)
com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:593)
com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:529)
com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:893)
com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1138)
com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:632)
com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.java:59)
com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.java:73)
com.gosselinchristian.SSLPokeServlet.doGet(SSLPokeServlet.java:86)

The code:

protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
    try {

        System.out.println(getClasspathString());
        System.out.println(getPropertiesString());

        SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory
                .getDefault();
        SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket(
                "some_server", 443);

        InputStream in = sslsocket.getInputStream();
        OutputStream out = sslsocket.getOutputStream();



        // Write a test byte to get a reaction :)
        out.write(1);

        while (in.available() > 0) {
            System.out.print(in.read());
        }

        System.out.println("Successfully connected");

    } catch (Exception exception) {
        exception.printStackTrace();
    }
}

Some tomcat startup options:

JAVA_OPTS='-server -Dapp.name=TEST -Dfile.encoding=ISO-8859-1 -XX:PermSize=128m  -XX:MaxPermSize=128m -Xms512m -Xmx2048m -Djava.protocol.handler.pkgs=com.sun.net.ssl.internal.www.protocol -Djavax.net.ssl.trustStore=/export/home/user/some_server_certs -Djavax.net.ssl.trustStorePassword=changeit -Djavax.net.debug=all'

The same code, same jvm, same certificate works in other environments. Anyone has an idea of where this can go wrong ?

1
  • btw I was able to eliminate tomcat from the equation by reproducing the problem by simply running a Java class on the prompt. The class is the SSLPoke found here and the command line is: java -Djavax.net.ssl.trustStore=./some_server_certs -Djavax.net.debug=all SSLPoke some_server.com 443
    – cgos
    Commented May 27, 2011 at 11:58

3 Answers 3

1

-Djava.protocol.handler.pkgs=com.sun.net.ssl.internal.www.protocol

Get rid of that for a start, it is seven years out of date. It was for JDK 1.3 only.

There is something wrong with your JRE installation. Reinstall, and then make sure Tomcat is using the newly installed version.

1
  • thanks for the tips, I already re-installed the JRE from scratch tonight using the self-extracting binaries. I also tried two other JDK installations.
    – cgos
    Commented May 27, 2011 at 3:15
1

The javax.crypto.SunJCE_b class resides in <JAVA_HOME>/lib/jce.jar of the Sun JDK/JRE. It should ideally be loaded by the bootstrap classloader. The failure to load this class indicates something amiss with the classloading mechanism for your web-application, and possibly for Tomcat as well.

You might want to check

  • if the JRE/JDK contains this JAR.
  • if the CLASSPATH variable is being set in a manner, that causes a different archive to be loaded, or not be loaded at all. This point usually doesn't apply as the bootstrap classloader should load the class, instead of the system classloader (which relies on this environment variable).
  • if any of your applications is using AOP-style techniques to instrument the javax.crypto.* classes. You might want to configure such an application to exclude these classes (primarily) from instrumentation. In short, verify for custom classloader implementations.
2
  • All JRE I've tried contained jce.jar. On my latest attempt (see the new comment under the question) I have no other classpath then JAVA_HOME. No AOP, very basic java class that simply open an SSLSocket.
    – cgos
    Commented May 27, 2011 at 12:10
  • an update, after the sys admin installed all the latest patches the java/ssl problem disappeared. Glad. I was about to try modifying the securtity provider as shown here
    – cgos
    Commented May 28, 2011 at 11:30
1

This is an old post, but I'm just responding anyway, in case it's relevant for others who stumble upon this. We have encountered this error on our servers, and the issue was actually related to the open file limit. Check your open file limit. If it's something like 1024 then you probably have the same issue. Increase your open file limit for the user that Tomcat is running as.

Not the answer you're looking for? Browse other questions tagged or ask your own question.