Load JDBC Driver引起的死锁

在初始化JDBC Connection Pool的时候出现了死锁。

 经分析,该死锁出现的前提为:

1. Load 不同的JDBC Driver;

2. 要在不同的Thread中。

代码如下:

public class PoolTest {
	
	public static void main(String[] args) throws Exception {
		boolean dead = true;
		if (!dead) {
			Class.forName("net.sourceforge.jtds.jdbc.Driver");
			Class.forName("org.h2.Driver");
		}
		Thread a = new Thread(new PoolThreadA());
		Thread b= new Thread(new PoolThreadB());
		a.start();
		b.start();
	}
}

class PoolThreadA implements Runnable {
	@Override
	public void run() {
		DataSource ds = initDataSource();
		
		try {
			Connection c = ds.getConnection();
		} catch (Exception e) {
			
		}
	}
	
	private static DataSource initDataSource() {
        String connectionString = "jdbc:jtds:sqlserver://10.16.33.204:1433;databaseName=master";
        PoolProperties p = new PoolProperties();
        p.setUrl(connectionString);
        p.setDriverClassName("net.sourceforge.jtds.jdbc.Driver");
        p.setUsername("sa");
        p.setPassword("Oliver123");
        p.setJmxEnabled(true);
        p.setTestWhileIdle(false);
        p.setTestOnBorrow(true);
        p.setValidationQuery("SELECT 1");
        p.setTestOnReturn(false);
        p.setValidationInterval(0);
        p.setTimeBetweenEvictionRunsMillis(30000);
        p.setMinIdle(100);
        p.setInitialSize(10);
        p.setMaxWait(10000);
        p.setRemoveAbandonedTimeout(60);
        p.setMinEvictableIdleTimeMillis(30000);
        p.setMinIdle(10);
        p.setMaxActive(0);
        p.setLogAbandoned(true);
        p.setRemoveAbandoned(true);
        p.setJdbcInterceptors(
                "org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"+
                "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer;" 
                );
        DataSource datasource = new DataSource();
        datasource.setPoolProperties(p);
        return datasource;
    }
	
}

class PoolThreadB implements Runnable{
	@Override
	public void run() {
		DataSource ds = initDataSource();
		
		try {
			Connection c = ds.getConnection();
		} catch (Exception e) {
			
		}
	}
	
	private static DataSource initDataSource() {
        String connectionString = "jdbc:h2:mem:test;MVCC=TRUE;MODE=Oracle;MULTI_THREADED=TRUE;DB_CLOSE_DELAY=-1";
        PoolProperties p = new PoolProperties();
        p.setUrl(connectionString);
        p.setDriverClassName("org.h2.Driver");
        p.setUsername("sa");
        p.setPassword("");
        p.setJmxEnabled(true);
        p.setTestWhileIdle(false);
        p.setTestOnBorrow(true);
        p.setValidationQuery("SELECT 1");
        p.setTestOnReturn(false);
        p.setValidationInterval(0);
        p.setTimeBetweenEvictionRunsMillis(30000);
        p.setMinIdle(100);
        p.setInitialSize(10);
        p.setMaxWait(10000);
        p.setRemoveAbandonedTimeout(60);
        p.setMinEvictableIdleTimeMillis(30000);
        p.setMinIdle(10);
        p.setMaxActive(0);
        p.setLogAbandoned(true);
        p.setRemoveAbandoned(true);
        p.setJdbcInterceptors(
                "org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"+
                "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer;" 
                );
        DataSource datasource = new DataSource();
        datasource.setPoolProperties(p);
        return datasource;
    }
}


经查询,该错误为Java JDBC的SQL Manager一个设计的漏洞引起的。网上已经有很多讨论的文章:

比如 https://m.oschina.net/blog/289120

解决方法是把Load Class的地方放到线程外面。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值