title: Occasional NullPointerException in ResultSetImpl.checkColumnBounds or ResultSetImpl.getStringInternal
body: <p>First of all, please don't close this as duplicate of What is <code>NullPointerException</code> and how to fix it. I know what is <code>NullPointerException</code>, and I know how to solve it in my own code, but not when it is thrown by <strong>mysql-connector-java-5.1.36-bin.jar</strong>, which I have no control over.</p>
  
  <p>We encountered the exception when running a common DB query, on a mySQL DB, that works most of the time. We started seeing this exception after deploying a new version, but the query in which it occurs didn't change in a long time.</p>
  
  <p>Here's how the query looks like (with some necessary simplifications). I surrounded it with some of the logic performed before and after. The actual code is not all in a single method, but I put it in a single block to make it easier to understand.</p>
  
  <pre><code>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();
  </code></pre>
  
  <p><code>res.getByte(8)</code> causes a <code>NullPointerException</code> with the following call stack :</p>
  
  <blockquote>
    <p>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)</p>
  </blockquote>
  
  <p>I searched for the source code of the relevant mysql-connector version and found this (taken from <a href="http://grepcode.com/file/repo1.maven.org/maven2/mysql/mysql-connector-java/5.1.36/com/mysql/jdbc/ResultSetImpl.java#ResultSetImpl.checkColumnBounds%28int%29" rel="nofollow noreferrer">here</a>):</p>
  
  <pre><code>756 protected final void checkColumnBounds(int columnIndex) throws SQLException {
  757     synchronized (checkClosed().getConnectionMutex()) {    
  758         if ((columnIndex &lt; 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 &gt; 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 }
  </code></pre>
  
  <p>As you can see, the exception occurs on this line :</p>
  
  <pre><code>} else if ((columnIndex &gt; this.fields.length)) {   
  </code></pre>
  
  <p>which means <code>this.fields</code> somehow became <code>null</code>.</p>
  
  <p>The closest thing I could find was <a href="https://stackoverflow.com/questions/32834387/intermittent-java-mysql-connection-exception-play-java">this question</a>, which has no answer.</p>
  
  <p>I suspect the issue is not in the query I posted. Perhaps something went wrong with the <code>Connection</code> instance due to some other statements we are running on the same connection. All I can say is that we close every statement right after we execute it and read the data from its <code>ResultSet</code>.</p>
  
  <p><strong>EDIT (1/19/2017):</strong></p>
  
  <p>I couldn't recreate the error in my development environment. I thought it might be some mysql-connector bug triggered when the same connection is used for a long time. I limited the above loop to load at most 6 elements at a time. In addition, we upgraded the mysql-connector version to 5.1.40.</p>
  
  <p>We still see <code>NullPointerException</code>s in <code>ResultSetImpl</code>, but this time at a different location.</p>
  
  <p>The stack trace is :</p>
  
  <blockquote>
    <p>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)</p>
  </blockquote>
  
  <p>which implies this time the exception was thrown as a result of one of our <code>res.getString()</code> calls (I don't know which one).</p>
  
  <p>I found the source for <strong>mysql-connector-java-5.1.40-bin.jar</strong> <a href="https://github.com/mysql/mysql-connector-j/blob/release/5.1/src/com/mysql/jdbc/ResultSetImpl.java#L5294" rel="nofollow noreferrer">here</a> and the relevant code is:</p>
  
  <pre><code>5292            // Handles timezone conversion and zero-date behavior
  5293
  5294            if (checkDateTypes &amp;&amp; !this.connection.getNoDatetimeStringSync()) {
  5295                switch (metadata.getSQLType()) {
  </code></pre>
  
  <p>which implies <code>this.connection</code> is null. <code>this.connection</code> is an instance variable of type <code>MySQLConnection</code>, which gets initialized in the constructors of <code>ResultSetImpl</code> and is only set to null when <code>public void realClose(boolean calledExplicitly)</code> is called (it is called by <code>public void close()</code>, which, according to the documentation within the source, is called when <code>ResultSet.close()</code> is called). We are definitely not closing the <code>ResultSet</code> prior to reading all the data from it.</p>
  
  <p>Any ideas how to proceed?</p>