偶尔 NullPointerException in ResultSetImpl.checkColumnBounds 或 ResultSetImpl.getStringInternal
首先,请不要将其作为“是什么以及如何解决”的副本关闭。我知道是什么,我知道如何在我自己的代码中解决它,但是当它被mysql-connector-java-5.1.36-bin.jar抛出时,我无法控制。NullPointerException
NullPointerException
我们在mySQL数据库上运行通用数据库查询时遇到了异常,这种查询大部分时间都有效。在部署新版本后,我们开始看到此异常,但发生此异常的查询在很长一段时间内都没有更改。
下面是查询的外观(带有一些必要的简化)。我用一些之前和之后执行的逻辑包围了它。实际的代码并不都在一个方法中,但我把它放在一个块中,以使其更容易理解。
Connection conn = ... // the connection is open
...
for (String someID : someIDs) {
SomeClass sc = null;
PreparedStatement
stmt = conn.prepareStatement ("SELECT A, B, C, D, E, F, G, H FROM T WHERE A = ?");
stmt.setString (1, "someID");
ResultSet res = stmt.executeQuery ();
if (res.next ()) {
sc = new SomeClass ();
sc.setA (res.getString (1));
sc.setB (res.getString (2));
sc.setC (res.getString (3));
sc.setD (res.getString (4));
sc.setE (res.getString (5));
sc.setF (res.getInt (6));
sc.setG (res.getString (7));
sc.setH (res.getByte (8)); // the exception is thrown here
}
stmt.close ();
conn.commit ();
if (sc != null) {
// do some processing that involves loading other records from the
// DB using the same connection
}
}
conn.close();
res.getByte(8)
导致 具有以下调用堆栈的 a:NullPointerException
com.mysql.jdbc.ResultSetImpl.checkColumnBounds(ResultSetImpl.java:763) com.mysql.jdbc.ResultSetImpl.getStringInternal(ResultSetImpl.java:5251) com.mysql.jdbc.ResultSetImpl.getString(ResultSetImpl.java:5173) com.mysql.jdbc.ResultSetImpl.getByte(ResultSetImpl.java:1650) org.apache.tomcat.dbcp.dbcp2.DelegatingResultSet.getByte(DelegatingResultSet.java:206) org.apache.tomcat.dbcp.dbcp2.DelegatingResultSet.getByte(DelegatingResultSet.java:206)
我搜索了相关mysql连接器版本的源代码,并找到了这个(取自这里):
756 protected final void checkColumnBounds(int columnIndex) throws SQLException {
757 synchronized (checkClosed().getConnectionMutex()) {
758 if ((columnIndex < 1)) {
759 throw SQLError.createSQLException(
760 Messages.getString("ResultSet.Column_Index_out_of_range_low",
761 new Object[] { Integer.valueOf(columnIndex), Integer.valueOf(this.fields.length) }), SQLError.SQL_STATE_ILLEGAL_ARGUMENT,
762 getExceptionInterceptor());
763 } else if ((columnIndex > this.fields.length)) {
764 throw SQLError.createSQLException(
765 Messages.getString("ResultSet.Column_Index_out_of_range_high",
766 new Object[] { Integer.valueOf(columnIndex), Integer.valueOf(this.fields.length) }), SQLError.SQL_STATE_ILLEGAL_ARGUMENT,
767 getExceptionInterceptor());
768 }
769
770 if (this.profileSql || this.useUsageAdvisor) {
771 this.columnUsed[columnIndex - 1] = true;
772 }
773 }
774 }
如您所见,异常发生在以下行:
} else if ((columnIndex > this.fields.length)) {
这意味着以某种方式成为.this.fields
null
我能找到的最接近的东西是这个问题,它没有答案。
我怀疑问题不在我发布的查询中。也许由于我们在同一连接上运行的其他一些语句,实例出了问题。我只能说,我们在执行每个语句后立即关闭它,并从其中读取数据。Connection
ResultSet
编辑 (1/19/2017):
我无法在开发环境中重现错误。我认为这可能是在长时间使用相同的连接时触发的一些mysql连接器错误。我将上述循环限制为一次最多加载6个元素。此外,我们还将 mysql 连接器版本升级到了 5.1.40。
我们仍然在 中看到 s,但这次是在不同的位置。NullPointerException
ResultSetImpl
堆栈跟踪为:
com.mysql.jdbc.ResultSetImpl.getStringInternal(ResultSetImpl.java:5294) com.mysql.jdbc.ResultSetImpl.getString(ResultSetImpl.java:5151) org.apache.tomcat.dbcp.dbcp2.DelegatingResultSet.getString(DelegatingResultSet.java:198) org.apache.tomcat.dbcp.dbcp2.DelegatingResultSet.getString(DelegatingResultSet.java:198)
这意味着这次异常是由于我们的一个调用而引发的(我不知道是哪一个)。res.getString()
我找到了mysql-connector-java-5.1.40-bin的源代码.jar在这里,相关代码是:
5292 // Handles timezone conversion and zero-date behavior
5293
5294 if (checkDateTypes && !this.connection.getNoDatetimeStringSync()) {
5295 switch (metadata.getSQLType()) {
这意味着为空。 是类型的实例变量,它在 的构造函数中初始化,并且仅在调用时才设置为 null(它由 调用,根据源代码中的文档,在调用时调用)。在从中读取所有数据之前,我们绝对不会关闭。this.connection
this.connection
MySQLConnection
ResultSetImpl
public void realClose(boolean calledExplicitly)
public void close()
ResultSet.close()
ResultSet
任何想法如何进行?