谷歌返回了很多在 C3P0 中遇到死锁问题的人,但似乎没有一个解决方案适用(大多数人建议设置maxStatements = 0
和maxStatementsPerConnection = 0
,我们都有这两个)。
我正在使用ComboPooledDataSource
来自 C3P0 的,初始化为;
cpds = new ComboPooledDataSource();
cpds.setDriverClass("org.postgresql.Driver");
cpds.setJdbcUrl("jdbc:postgresql://" + host + ":5432/" + database);
cpds.setUser(user);
cpds.setPassword(pass);
我的query
功能看起来像;
public static List<Map<String, Object>> query(String q) {
Connection c = null;
Statement s = null;
ResultSet r = null;
try {
c = cpds.getConnection();
s = c.createStatement();
s.executeQuery(q);
r = s.getResultSet();
/* parse result set into results List<Map> */
return results;
}
catch(Exception e) { MyUtils.logException(e); }
finally {
closeQuietly(r);
closeQuietly(s);
closeQuietly(c);
}
return null;
}
query()
尽管方法到达了return results;
行,但没有查询返回。问题是该finally
块正在挂起。我已经确定这closeQuietly(s);
是无限期悬挂的线路。
有问题的closeQuietly()
方法如您所料;
public static void closeQuietly(Statement s) {
try { if(s != null) s.close(); }
catch(Exception e) { MyUtils.logException(e); }
}
为什么这种方法会坚持下去s.close()
?我想这与我使用 C3P0 的方式有关。
我完整的 C3P0 配置(几乎完全默认)可以在这里查看 -> http://pastebin.com/K8XDdiBg
MyUtils.logException();
看起来像;
public static void logException(Exception e) {
StackTraceElement ste[] = e.getStackTrace();
String message = " !ERROR!: ";
for(int i = 0; i < ste.length; i++) {
if(ste[i].getClassName().contains("packagename")) {
message += String.format("%s at %s:%d", e.toString(), ste[i].getFileName(), ste[i].getLineNumber());
break;
}
}
System.err.println(message);
}
如果我删除closeQuietly(s);
线路,一切都会顺利进行。关闭ResultSet
和Connection
对象都可以正常工作 - 当然除了连接饥饿。