2013年2月25日 星期一

在 OpenJDK 上使用 JavaMail 的問題

目前還在尋找問題中。
已經發現的問題是 JavaMail 在建立 Socket 連線時會噴以下的 Exception:
javax.mail.MessagingException: Could not connect to SMTP host: smtp.gmail.com, port: 465;
  nested exception is:
        java.io.IOException: Can't create MailSSLSocketFactory
        at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1966)
        at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:654)
        at javax.mail.Service.connect(Service.java:295)
        at javax.mail.Service.connect(Service.java:176)
        at org.twgogo.jimwayne.mail.MailService.sendMail(MailService.java:266)
        at org.twgogo.jimwayne.mail.MailService.sendMail(MailService.java:157)
        at org.twgogo.jimwayne.main.Main.sendMail(Main.java:52)
        at org.twgogo.jimwayne.main.Main.main(Main.java:23)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:616)
        at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)
Caused by: java.io.IOException: Can't create MailSSLSocketFactory
        at com.sun.mail.util.SocketFetcher.createSocket(SocketFetcher.java:344)
        at com.sun.mail.util.SocketFetcher.getSocket(SocketFetcher.java:239)
        at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1929)
        ... 12 more
Caused by: java.security.KeyStoreException: problem accessing trust storejava.io.EOFException
        at sun.security.ssl.TrustManagerFactoryImpl.engineInit(TrustManagerFactoryImpl.java:75)
        at javax.net.ssl.TrustManagerFactory.init(TrustManagerFactory.java:247)
        at com.sun.mail.util.MailSSLSocketFactory$MailTrustManager.<init>(MailSSLSocketFactory.java:333)
        at com.sun.mail.util.MailSSLSocketFactory$MailTrustManager.<init>(MailSSLSocketFactory.java:331)
        at com.sun.mail.util.MailSSLSocketFactory.<init>(MailSSLSocketFactory.java:115)
        at com.sun.mail.util.MailSSLSocketFactory.<init>(MailSSLSocketFactory.java:94)
        at com.sun.mail.util.SocketFetcher.createSocket(SocketFetcher.java:337)
        ... 14 more


我把建立 Socket 的程式碼獨立拿出來執行時,發現 Exception 變成以下的內容:
java.net.SocketException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.DefaultSSLContextImpl)
        at javax.net.ssl.DefaultSSLSocketFactory.throwException(SSLSocketFactory.java:196)
        at javax.net.ssl.DefaultSSLSocketFactory.createSocket(SSLSocketFactory.java:203)
        at org.twgogo.jimwayne.socket.SocketTester.createSocket(SocketTester.java:16)
        at org.twgogo.jimwayne.main.TestMain.main(TestMain.java:15)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:616)
        at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)
Caused by: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.DefaultSSLContextImpl)
        at java.security.Provider$Service.newInstance(Provider.java:1262)
        at sun.security.jca.GetInstance.getInstance(GetInstance.java:236)
        at sun.security.jca.GetInstance.getInstance(GetInstance.java:164)
        at javax.net.ssl.SSLContext.getInstance(SSLContext.java:142)
        at javax.net.ssl.SSLContext.getDefault(SSLContext.java:85)
        at javax.net.ssl.SSLSocketFactory.getDefault(SSLSocketFactory.java:119)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:616)
        at org.twgogo.jimwayne.socket.SocketTester.getSocketFactory(SocketTester.java:42)
        at org.twgogo.jimwayne.socket.SocketTester.createSocket(SocketTester.java:15)
        ... 6 more
Caused by: java.io.EOFException
        at java.io.DataInputStream.readInt(DataInputStream.java:392)
        at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:645)
        at sun.security.provider.JavaKeyStore$JKS.engineLoad(JavaKeyStore.java:55)
        at java.security.KeyStore.load(KeyStore.java:1201)
        at sun.security.ssl.TrustManagerFactoryImpl.getCacertsKeyStore(TrustManagerFactoryImpl.java:221)
        at sun.security.ssl.DefaultSSLContextImpl.getDefaultTrustManager(DefaultSSLContextImpl.java:87)
        at sun.security.ssl.DefaultSSLContextImpl.<init>(DefaultSSLContextImpl.java:57)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:532)
        at java.lang.Class.newInstance0(Class.java:372)
        at java.lang.Class.newInstance(Class.java:325)
        at java.security.Provider$Service.newInstance(Provider.java:1238)
        ... 17 more

看起來有點奇怪,因為獨立抽出來的程式碼中並沒有指定要用 SunJSSE 的東西
只有指定 SocketFactory 要用 javax.net.ssl.SSLSocketFactory。
而 Google 時看起來 OpenJDK 內建應該有 javax.net.ssl.SSLSocketFactory 這個 class
不知道為什麼程式跑一跑自己會跑去抓 SunJSSE。
雖然也有可能是本來就要去找 SunJSSE 的某些東西,但因為網路上搜尋時好像沒有看到有人說 JavaMail 在 OpenJDK 上沒辦法用
理論上應該比較有可能的還是我有哪裡弄錯了才對。

Still keep working!

2013-02-26 補充
後來交給廠商處理,廠商說他們用的 OpenJDK 是自己客製化過的版本,所以並不是 OpenJDK 本身有問題...
他們更新了自己客製化的 OpenJDK 後,這個問題就消失了...。
後來雖然又有出現 Read timeout 的問題,但把 JavaMail 版本從 1.4.4 升級成 1.4.6 就好了
不知道是被什麼影響到的~原本我們自己的環境中用 Sun JDK 1.6.0 + JavaMail 1.4.4 一直都用得很好。

參考資料:
1、SSL with javamail not working
2、Is Java SSL broken in OpenJDK on Ubuntu?

沒有留言: