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

Strange crashes in JDBC code in multithreaded application.

From: "L(dot) Rahyen" <research(at)science(dot)su>
To: pgsql-jdbc(at)postgresql(dot)org
Subject: Strange crashes in JDBC code in multithreaded application.
Date: 2007-08-05 02:16:12
Message-ID: 200708050216.12872.research@science.su (view raw or flat)
Thread:
Lists: pgsql-jdbc
	I'm not on the list so please don't forget to CC me.

	First, what I'm doing, briefly. I have multithreaded proxy-server (it is 
based on few years ago abandoned project). It wants to store information on 
every page load/refresh to the database. And this works in almost all 
cases... Almost. It is obvious that this is not acceptable because I have 
broken database as a result; it should work in all cases of course to be 
useful in the real world.
	Now, the details. Here is my functions to connect to the database and 
initialize a statement:

private static Connection conn = null;
private static Statement stat = null;

final private void connect_to_psql()
{
	try
	{
		if(mgr.loglevel>3) System.err.println("Connecting to PostgreSQL...");
		// Step 1: Load the JDBC driver.
		Class.forName("org.postgresql.Driver");
		// Step 2: Establish the connection to the database.
		String url = "jdbc:" + mgr.psql_url;
		conn = DriverManager.getConnection(url, mgr.psql_user, mgr.psql_password);
	}
	catch (Exception e)
	{
		System.err.println("Got an exception when connecting to PostgreSQL database 
erver! ");
		System.err.println(e.getMessage() );
		e.printStackTrace();
		System.exit(8);
	}
}

final private void initialize_statement()
{
	try
	{
		stat = conn.createStatement();
	}
	catch (SQLException e)
	{
		System.out.println("We got an exception while creating a PostgreSQL 
statement: that probably means we're no longer connected. ");
		System.err.println(e.getMessage() );
		e.printStackTrace();
		System.exit(9);
	}
}

...
	if(conn == null)
		connect_to_psql();
	if(stat == null)
		initialize_statement();
...

	conn and stat assigments - that's all is really important here. I call these 
functions only once for all threads. Everything works great in almost 
all cases but sometimes (see below what "sometimes" exactly means here) I get 
this crash when I call stat.executeUpdate(query):

Exception in thread "Thread-518" java.lang.NullPointerException
   at 
org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:179)
   at 
org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:437)
   at 
org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:339)
   at 
org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:285)
...

	This crash is "hard": it crashes whole thread (but not the main program of 
course) even if I have related catch block. So I never have a chance to 
reconnect to the database from the thread to "fix" the problem. It doesn't 
matter at all what query I use. I even can use exactly the same query every 
time (constant string) and still have JDBC to crashes *sometimes*.
	Now, what "sometimes" means? Sometimes I get above error every 1-3 calls of 
executeUpdate(), sometimes once every 200-400 calls (this is most common 
case). In other words this is non-uniform, at least at first impression. From 
the JDBC user point of view it doesn't matter what query I use or how big is 
uptime of my proxy or database connection. This is just happens and I cannot 
prevent it.
	If I change "private static Statement stat = null;" to "private Statement 
stat = null;" and get in this way indepedant  stat variable for each thread 
nothing changes. I still get java.lang.NullPointerException sometimes and it 
is almost the same as one above (please note that crash above is with a 
little older JDBC release and crash below is with newest JDBC release, as you 
can see nothing changes - just minor difference in line numbers):

Exception in thread "Thread-108" java.lang.NullPointerException
   at 
org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:182)
   at 
org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:452)
   at 
org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:337)
   at 
org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:283)
   at cacheobject.load_object(cacheobject.java:680)
   at cacheobject.make_request(cacheobject.java:176)
   at mgr.process_request(mgr.java:1488)
   at httpreq.run(httpreq.java:282)
   at java.lang.Thread.run(libgcj.so.70)

	Now, I see only two possibilities:

	1) This is a bug in JDBC. Is JDBC thread-safe? Is it supposed to be 
thread-safe by design? Obviously if not then initializing conn 
every time will be inefficient and I need to write a separate server to 
execute PSQL queries because I want to connect only once to the DB.
	2) I'm doing multithreading with JDBC in a wrong way. Do I need anything 
special? Can I use same conn in all threads?

	Feel free to ask if you additional question. I think that above examples show 
the whole problem because that's only JDBC code in my proxy currently.
	Sorry if there is something obvious I have missed - this is a first time I 
write multithreading code in Java.

Responses

pgsql-jdbc by date

Next:From: Kris JurkaDate: 2007-08-05 02:57:50
Subject: Re: Strange crashes in JDBC code in multithreaded application.
Previous:From: Laszlo HornyakDate: 2007-08-04 06:47:27
Subject: Re: statement caching patch from Laszlo Hornyak for review

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