天天看点

IBM JDK下访问SSL/HTTPS时候ClassNotFoundException解决方法

项目代码会使用HTTPS,之前一直在Sun JDK+Tomcat上开发。换到QA环境后使用的是Websphere,默认是IBM JDK。

1. QA报问题,预料中,因为没导过HTTPS的证书,导完重启,问题解决。

2. 再重启QA,又出问题,看log, java.net.SocketException: Cannot find the specified class java.security.PrivilegedActionException: java.lang.ClassNotFoundException: com.ibm.websphere.ssl.protocol.SSLSocketFactory 。网上查查,要设置

ssl.SocketFactory.provider=com.ibm.jsse2.SSLSocketFactoryImpl

ssl.ServerSocketFactory.provider=com.ibm.jsse2.SSLServerSocketFactoryImpl。

只不过他们是用Security里的方法设,我是在Websphere里设参数,应该没问题。 重启,问题解决。

3.再重启,问题又出现,还是一样的log内容;再重启,重启,重启...发现时好时坏。这种问题最让我崩溃。觉得应该是IBM JDK的问题。把环境变量设成Sun JDK。重启,问题解决。

4 .再重启,问题又来. . .。查Websphere的启动脚本,发现不管系统设什么JDK,Websphere都会用自带的IBM JDK。上网查,听说Websphere在windows下只支持自带的JDK。完了,也换不成了。马上要下班,还要回珠海。盲目试一试,把参数设成

ssl.SocketFactory.provider=com.ibm.websphere.ssl.protocol.SSLSocketFactory

ssl.ServerSocketFactory.provider=com.ibm.websphdere.ssl.protocol.SSLServerSocketFactory。

重启,让同事看看,背着电脑回珠海。路上想着觉得这样设怎么都没道理会成功。如果是按第二步的设置,是让系统尝试不要找com.ibm.websphere.ssl.protocol.SSLSocketFactory,而是去找 com.ibm.jsse2.SSLSocketFactoryImpl,我现在这样设,又让它去找 com.ibm.websphere.ssl.protocol.SSLSocketFactory,没有能行的道理。果然,同事说不行。

5.在车上,打开电脑,认真看看google结果。其中一篇http://www.eclipsezone.com/eclipse/forums/t97939.html 提到他也是这个问题。刚好,我们也是OSGi,环境也差不多。

他是OSGi的程序会用SSL,另外一个程序A也会用SSL;OSGi程序会调用程序A。测试结果是如果程序A先启动就问题。原因分析:SSL的实现在jvm可能只允许加载一份,如果OSGi先启动,会去加载com.ibm.jsse2.SSLSocketFactoryImpl,程序A也会使用这个实现;如果程序A先启动会去使用 com.ibm.websphdere.ssl.protocol.SSLServerSocketFactory,OSGi启动的时候也会试图去使用这个实现,但是OSGi的ClassLoader是独立的,这个时候它找不到这个类,没法加载。为什么找不到呢?原因下面会给出。

匹配到我们的情况,我们没有程序A,有可能会引起的就只有Web服务器可能会使用SSL了。猜想,那是不是在启动服务器的时候,在OSGi没启动完前不要试图去访问HTTPS就可以呢?(之前在重启的时候经常在没重启完就试图去访问)。不敢肯定,在车上也没法试。

继续看搜索# Default JSSE socket factories

#ssl.SocketFactory.provider=com.ibm.jsse2.SSLSocketFactoryImpl

#ssl.ServerSocketFactory.provider=com.ibm.jsse2.SSLServerSocketFactoryImpl

# WebSphere socket factories (in cryptosf.jar)

ssl.SocketFactory.provider=com.ibm.websphere.ssl.protocol.SSLSocketFactory

ssl.ServerSocketFactory.provider=com.ibm.websphdere.ssl.protocol.SSLServerSocketFactory

可以更改jvm默认的SSL实现,这样不管是不是OGSi里,我们都可以强制把SSL实现使用com.ibm.jsse2.SSLSocketFactoryImpl 。兴奋,打电话叫同事试一下把实现替换,重启,果然可以。

分析类加载不到的原因:

看上面的设置文件,有一段# WebSphere socket factories (in cryptosf.jar ),看来 com.ibm.jsse2.SSLSocketFactoryImpl是jvm自带,但是 com.ibm.websphere.ssl.protocol.SSLSocketFactory在一个jar里,我们的OSGi应该也没导入这个类,怪不得OSGi找不到了。

终极解决方法: 更改 <IBM_JAVA_HOME>/jre/lib/security/java.security里的设置,改成

# Default JSSE socket factories

ssl.SocketFactory.provider=com.ibm.jsse2.SSLSocketFactoryImpl

ssl.ServerSocketFactory.provider=com.ibm.jsse2.SSLServerSocketFactoryImpl

# WebSphere socket factories (in cryptosf.jar)

#ssl.SocketFactory.provider=com.ibm.websphere.ssl.protocol.SSLSocketFactory

#ssl.ServerSocketFactory.provider=com.ibm.websphdere.ssl.protocol.SSLServerSocketFactory

应该换到任何地方都可以用了^_^。

继续阅读