[Access][Microsoft][ODBC 驱动程序管理器] 无效的字符串或缓冲区长度 Invalid string or buffer length

背景描述:

项目中,客户的工厂有一台检测产品指标的检测仪,其检测结果存储在本地电脑的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位的时候才会有问题。

解决方法:
避免使用ResultSet.getObject()/getString(),根据数据库的类型,如果是数字使用getLong,如果是字符串使用getBytes来进行读取。比如:
1 String remark = new String(rs.getBytes(4), "gbk");

至此,此问题再也没有再复现过,问题解决!

原文地址:https://www.cnblogs.com/wanggangblog/p/15384216.html