Skip site navigation (1) Skip section navigation (2)

Unexpected NullPointerException in "processDeadParsedQueries()" - suggested fix

From: Morten Andersen <moa-ml(at)instadia(dot)net>
To: pgsql-jdbc(at)postgresql(dot)org
Subject: Unexpected NullPointerException in "processDeadParsedQueries()" - suggested fix
Date: 2006-12-20 12:15:56
Message-ID: (view raw, whole thread or download thread mbox)
Lists: pgsql-jdbc

In a multithreaded application I just got an unexpected 
NullPointerException from the depth's of the JDBC-drivers cleanup 
routine of parsed queries.

The driver I am using is the most recent JDBC3 driver, version 8.2-504.

During a batch-execution of a trivial PreparedStatement that generally 
works fine I got the NullPointerException below:

Exception in thread "Thread-5" java.lang.NullPointerException
         at org.postgresql.core.Utils.encodeUTF8(

[SNIP - rest of calling stacktrace - was outside the driver]

I have been browsing the CVS-repository and I think the code that 
generates this is the processDeadParsedQueries() below:

private void processDeadParsedQueries() throws IOException {
   PhantomReference deadQuery;
   while ((deadQuery = (PhantomReference)parsedQueryCleanupQueue.poll()) 
!= null)
     String statementName = (String)parsedQueryMap.remove(deadQuery); 
<--- RETURNS null?
     sendCloseStatement(statementName);  <--- TRIGGERS NullPointerException

I inserted the comments with "<---".

The reaon why it is possible for the parsedQueryMap to return a null 
statementName for the deadQuery key is quite a puzzle to me. Mostly I 
can only think of two reasons:

  1) The statementName for the deadQuery has already been removed. Given 
the code for registerParsedQuery() and processDeadParsedQueries() I 
can't see how this should be possible, as the 
java.lang.ref.ReferenceQueue is thread-safe (it doesn't say so in the 
API documentation, but that is what you would expect, and a quick glance 
at the JDK source also indicates that this is the case).

  2) The use of HashMap for the parsedQueryMap could be a problem in a 
multithreaded application, since it is not thread-safe? So a wild guess 
is that the thread executing the processDeadParsedQueries() does not 
"see" the value that was added to the hashmap by another thread in the 

Maybe some of you guys can see other ways this situation could arise? 
Otherwise I would suggest a combination of two solutions:

a) change parsedQueryMap to a synchronizedMap (either by the 
Collections.synchronizedMap or by using a Hashtable - or for JDK1.5+ the 
more "highspeed" java.util.concurrent.ConcurrentHashMap).


b) do an explicit check that the returned statementName is not null, 
i.e. change the body of the while-loop in processDeadParsedQueries to 
something along the lines:

String statementName = (String)parsedQueryMap.remove(deadQuery);
if (statementName != null) {

This should not be necessary (as far as I can tell?), since the 
ReferenceQueue should never contain the deadQuery before it has been 
added to the parsedQueryMap in registerParsedQuery() due to the contract 
for PhantomReference? But one should always be carefull with this kind 
of Thread-reasoning :-)

Please feel to come with any thoughts on this fix, and if you need more 
information on the exact code that executed the PreparedStatement, 
please also mail me.

Best Regards
Morten Andersen,
Instadia A/S, Denmark


pgsql-jdbc by date

Next:From: John LHDate: 2006-12-20 18:22:22
Subject: Driver Bug
Previous:From: Roman ChervotkinDate: 2006-12-20 11:35:20
Subject: The column name x was not found in this ResultSet

Privacy Policy | About PostgreSQL
Copyright © 1996-2017 The PostgreSQL Global Development Group