背景描述:
項目中,客戶的工廠有一台檢測產品指標的檢測儀,其檢測結果存儲在本地電腦的Access數據庫中。項目的目的是服務器連接這台電腦,通過rmi的方式進行連接,讀取這台電腦上的Access數據庫的mdb文件中的內容。
Java 在服務器上通過RMI的方式訪問客戶電腦上的Access數據庫中的內容的方法可以參考:https://blog.csdn.net/hongdi/article/details/5482470 中的介紹,很詳細了。
錯誤描述:
在讀取客戶電腦上的Access數據庫中的數據時,最開始一切都很正常,從某一時間點開始,報如下錯誤:
1 java.sql.SQLException: [Microsoft][ODBC 驅動程序管理器] 無效的字符串或緩沖區長度 2 at sun.jdbc.odbc.JdbcOdbc.createSQLException(Unknown Source) 3 at sun.jdbc.odbc.JdbcOdbc.standardError(Unknown Source) 4 at sun.jdbc.odbc.JdbcOdbc.SQLGetDataString(Unknown Source) 5 at sun.jdbc.odbc.JdbcOdbcResultSet.getDataString(Unknown Source) 6 at sun.jdbc.odbc.JdbcOdbcResultSet.getString(Unknown Source) 7 at org.objectweb.rmijdbc.RJResultSetServer.getString(RJResultSetServer.java:144) 8 at sun.reflect.GeneratedMethodAccessor59.invoke(Unknown Source) 9 at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 10 at java.lang.reflect.Method.invoke(Unknown Source) 11 at sun.rmi.server.UnicastServerRef.dispatch(Unknown Source) 12 at sun.rmi.transport.Transport$2.run(Unknown Source) 13 at sun.rmi.transport.Transport$2.run(Unknown Source) 14 at java.security.AccessController.doPrivileged(Native Method) 15 at sun.rmi.transport.Transport.serviceCall(Unknown Source) 16 at sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source) 17 at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source) 18 at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.access$400(Unknown Source) 19 at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$1.run(Unknown Source) 20 at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$1.run(Unknown Source) 21 at java.security.AccessController.doPrivileged(Native Method) 22 at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source) 23 at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) 24 at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) 25 at java.lang.Thread.run(Unknown Source) 26 at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:283) 27 at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:260) 28 at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:161) 29 at org.objectweb.rmijdbc.RJResultSetServer_Stub.getString(Unknown Source) 30 at org.objectweb.rmijdbc.RJResultSet.getString(RJResultSet.java:143)
經查,用戶的電腦的操作系統為64位Windows 7系統。同樣的代碼,當用戶的電腦是32位Windows XP時就好用,不報錯。
程序中讀取數據的代碼如下:
1 String sampNo = rs.getString(1);
經過不斷的查找,終於在這篇帖子上找到了問題的根源:https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8038751
是因為Jdk 1.6/7在64位操作系統上JDBC-ODBC橋上的Bug,導致在調用ResultSet.getObject()/getString()的時候隨機並且不定時的報出 [Microsoft][ODBC 驅動程序管理器] 無效的字符串或緩沖區長度 這個錯誤。並不是一定會報錯,可能是正常的運行了一段時間之后才報出來。
這也解釋了為什么當用戶電腦是Windows XP時讀取沒問題,當用戶是Windows 7 64位的時候才會有問題。
1 String remark = new String(rs.getBytes(4), "gbk");
至此,此問題再也沒有再復現過,問題解決!