Bug #38060 NullPointerException in getServerCharacterEncoding(), caused by isValid()
Submitted: 11 Jul 2008 23:15 Modified: 17 Jul 2008 14:10
Reporter: Ondra Zizka
Status: Analyzing
Category:Connector/J Severity:S2 (Serious)
Version:5.1.6 OS:Any
Assigned to: Target Version:
Tags: JDBC Connector NPE NullPointerException getServerCharacterEncoding()

[11 Jul 2008 23:15] Ondra Zizka
Description:
MySQL:  5.0.51a-3ubuntu5.1
JDBC:   5.1.5 (NetBeans bundled)

I'm getting an exception while processing some "documents" in a loop:

...
stmtInsertSpis.setString(1, sSpis);
...

INFO:   Processing item no. 2023 - folder INS 46/2008
SEVERE: null
java.lang.NullPointerException
at com.mysql.jdbc.ConnectionImpl.getServerCharacterEncoding(ConnectionImpl.java:3040)
 at com.mysql.jdbc.PreparedStatement.setString(PreparedStatement.java:4072)
 at cz.dynawest.isir.Conversion.ZpracujArchiv(Conversion.java:166)
 at cz.dynawest.isir.xmlvypis.Main.main(Main.java:49)

(sSpis is NOT null.)

How to repeat:
Hard to tell, this exception appears after several hundreds of rounds, but the exact
number differs. I'll download the Connector/J sources and try to investigate a bit.

In the project, I mix JDBC and IBatis, which use two different Connections.

Few last queries from the log are: (this is also typical sequence of one loop)

    9 Query       INSERT isir_spisy SET znacka = 'INS 46/2008', zalozeni = NOW()
   10 Query       rollback
   10 Query       INSERT INTO isir_osoby       (uid, jmeno, prijmeni, id_adresa_trvala,
id_adresa_prechodna, rc, nar, titul_pred, titul_za)       VALUES       ('MIVSJOSE161145 
1', 'Josef', 'Mivsk', null, null,         '451116036', null, '', '')       ON DUPLICATE
KEY UPDATE id = LAST_INSERT_ID(id), jmeno = VALUES(jmeno), prijmeni = VALUES(prijmeni),  
       id_adresa_trvala = VALUES(id_adresa_trvala), id_adresa_prechodna =
VALUES(id_adresa_prechodna),          rc = VALUES(rc), nar = VALUES(nar), titul_pred =
VALUES(titul_pred), titul_za = VALUES(titul_za)
    10 Query       SELECT LAST_INSERT_ID()
    10 Query       commit
    10 Query       rollback

Suggested fix:
.
[12 Jul 2008 0:04] Ondra Zizka
Also happens with Connector/J 5.1.6.

java.lang.NullPointerException
        at
com.mysql.jdbc.ConnectionImpl.getServerCharacterEncoding(ConnectionImpl.java:3040)
        at com.mysql.jdbc.PreparedStatement.setString(PreparedStatement.java:4072)
        at cz.dynawest.isir.Conversion.ZpracujArchiv(Conversion.java:166)
        at cz.dynawest.isir.xmlvypis.Main.main(Main.java:49)

public String getServerCharacterEncoding() {
  if (this.io.versionMeetsMinimum(4, 1, 0)) {
	return (String) this.serverVariables.get("character_set_server");
  } else {
  	return (String) this.serverVariables.get("character_set");
  }
}

Code lines reported by the exception differs from those in sources in
mysql-connector-java-5.1.6.tar.gz.
[12 Jul 2008 0:18] Ondra Zizka
So, it's the this.io - which is null upon that exception.

Maybe I should also mention that I use 64-bit linux kernel.
[12 Jul 2008 1:15] Ondra Zizka
Seems like Connection::isValid(int) is causing this.
In every round, I checked for the connection:

  conn.isValid(3);

When I commented this out, the NullPointerException does not appear.

Still, I consider it being a serious bug -> changing from S1 to S2.
[12 Jul 2008 1:39] Ondra Zizka
I think I've found the reason: It's the MySQL's implementation of isValid, which calls
abortInternal() in a thread without any synchronization of that thread, which in turn
runs for the period given by TimeOut. That's the reason for the random-ness of the bug.

I suggest:

1) Making abortInternal()  synchronized
2) Synchronize launched threads somehow; e.g. launching them via singleton which would
not allow more than one isValid()-thread running.
[12 Jul 2008 1:44] Ondra Zizka
And finally, I must say, I wonder how can anyone compile the Connector/J. I've tried, but
there are many overloading ambiguities and other problems blocking the build.
[16 Jul 2008 16:49] Ondra Zizka
I've created a JUnit test case, which reproduces the bug; adding as an attachment.

Libraries needed: JUnit and Connector/J 5.1.x.
[16 Jul 2008 16:51] Ondra Zizka
JUnit test case reproducing the bug.

Attachment: ConnectorJ_Bug_isValid_NPE_Test.java (application/octet_stream, text), 3.47 KiB.

[17 Jul 2008 14:10] Tonci Grgin
Hi Ondra and thanks for your report. Building c/J against JDK 1.6 is mistery to me too so
I'll forward this to c/J developers...
[17 Jul 2008 15:41] Mark Matthews
The issue is that you can't compile Connector/J with *just* JDK6, as the driver supports
JDBC4 and pre-JDBC4 APIs from the same codebase, and there are new classes and methods in
JDBC4 that aren't available pre-JDK6.

Therefore, the way it works is that you have to set JAVA_HOME to point to JDK-1.4 or 1.5,
and then set the Ant properties "com.mysql.jdbc.java6.javac" with the full path to your
JDK6 java compiler, and "com.mysql.jdbc.java6.rtjar" with the full path to your JDK6
runtime class libraries, when invoking Ant.