`

proxool 0.9.1,解决 Attempt to register duplicate pool 异常(转)

 
阅读更多

做项目的时候,遇见空异常,而且不是经常的,本来想将就的放过,可考虑到偶尔影响用户的正常使用,对用户体验非常不好,还是要花些时间查找问题的根源。结果如预料的那样,跟转发来的这篇博文讲述的性质一模一样。

 

同时再赞叹一声,转发来的这位博主,写的很详尽。下面是原文:

 

今天客户发来的日志中发现异常。该异常偶尔在程序启动的时候出现。

 

[java] view plaincopy
  1. java.sql.SQLException: org.logicalcobwebs.proxool.ProxoolException: Attempt to register duplicate pool called 'pool'  
  2.     at org.logicalcobwebs.proxool.ProxoolDriver.connect(ProxoolDriver.java:109)  
  3.     at java.sql.DriverManager.getConnection(DriverManager.java:582)  
  4.     at java.sql.DriverManager.getConnection(DriverManager.java:185)  


检查了下代码,似乎没有什么问题,一切都是按照proxool的教程中的example写的。于是把proxool的源代码下载,发现似乎真的有问题。

 

在类ProxoolDriver中,方法public Connection connect(String url, Properties info) 中,

 

[java] view plaincopy
  1. if (!ConnectionPoolManager.getInstance().isPoolExists(alias)) {  
  2.      ProxoolFacade.registerConnectionPool(url, info, false);     
  3.      cp = ConnectionPoolManager.getInstance().getConnectionPool(alias);  
  4. }   

 

这部分代码逻辑很简单,首先判断连接池的别名是否存在(isPoolExists),如果不存在,创建;已经存在,则直接获得连接。

在第2行的registerConnectionPool中,再次判断,该别名是否存在,如果已经存在,则抛出异常:

 

[java] view plaincopy
  1. if (!ConnectionPoolManager.getInstance().isPoolExists(alias)) {  
  2.      ConnectionPoolDefinition cpd = new ConnectionPoolDefinition(url, info, explicitRegister);  
  3.      registerConnectionPool(cpd);  
  4. else {  
  5.      throw new ProxoolException("Attempt to register duplicate pool called '" + alias + "'");  
  6. }  

 

那么,自然而然地考虑,这部分代码在并发的时候会出现问题。比如,下面两个thread, 分别调用getConnection

      Thread1                                                                                            Thread2

运行至(1), isPoolExists ? False                                                         运行至(1), isPoolExists ? False

运行至(2), 进入registerConnectionPool                                            运行至 (2) registerConnectionPool是static synchronized, 被阻塞住

创建完毕,返回                                                                               

                                                                                                     此时进入registerConnectionPool

                                                                                                     If 处判断为已经存在(因为Thread1已经创建了),进入04行的else块,在05行抛出异常

然后写一小段程序来测试下:

 

[java] view plaincopy
  1. import java.sql.*;  
  2.   
  3. public class TestForBug {  
  4.     public static void main(String[] arug) {  
  5.         new Thread(new T()).start();  
  6.         new Thread(new T()).start();  
  7.     }  
  8. }  
  9.   
  10. class T implements Runnable {  
  11.   
  12.     public void run() {  
  13.         Connection connection = null;  
  14.         try {  
  15.             Class.forName("org.logicalcobwebs.proxool.ProxoolDriver");  
  16.             try {  
  17.                 String url = "proxool.example:com.mysql.jdbc.Driver:jdbc:mysql://192.168.1.100:3306/mr";  
  18.                 String username = "root";  
  19.                 String password = "password";  
  20.                 connection = DriverManager.getConnection(url, username, password);  
  21.             } catch (SQLException e) {  
  22.                 System.err.println("Problem getting connection" + e.toString());  
  23.             }  
  24.             if (connection != null) {  
  25.                 System.out.println("Got connection :)");  
  26.             } else {  
  27.                 System.err.println("Didn't get connection, which probably means that no Driver accepted the URL");  
  28.             }  
  29.         } catch (ClassNotFoundException e) {  
  30.             System.err.println("Couldn't find driver " + e.getMessage());  
  31.         } finally {  
  32.             try {  
  33.                 if (connection != null) {  
  34.                     connection.close();  
  35.                 }  
  36.             } catch (SQLException e) {  
  37.                 System.err.println("Problem closing connection " + e);  
  38.             }  
  39.         }  
  40.     }  
  41. }  

这段程序十有八九会抛出那个异常。

这就怪了。Proxool用的也很多,为啥会犯这么低级的错误呢。后来在跟踪的时候,发现:

如果运行在JDK5下,就没问题;

如果运行在JDK6下,则有问题。

查看下运行的堆栈,为:

测试代码

java.sql.DriverManager.

org.logicalcobwebs.proxool.Driver

既然测试代码和proxool.Driver都没改变,那么就看看java.sql.DriverManager是怎么回事。

结果真相大白了。

JDK5中:

[java] view plaincopy
  1. public static synchronized Connection getConnection(String url,   
  2.     String user, String password) throws SQLException {    
  3.         //省略  
  4. }  

JDK6中:

[java] view plaincopy
  1. public static Connection getConnection(String url,   
  2.     String user, String password) throws SQLException {    
  3.         //省略  
  4. }  

 

也就是,上面说的并发的问题,在JDK5中是同步的。因为DriverManager里面的方法就是同步的。但是在6中就不是了。这就是为啥上面的isPoolExists的代码失效的原因。也就是说,在JDK6中,proxool可能会出现这个问题。

那么解决也很简单,修改ProxoolDriver,把connect方法加上synchronized即可:

 

[java] view plaincopy
  1. public synchronized Connection connect(String url, Properties info) {  
  2.     //省略  
  3. }  

 

 

 

 

原文链接:http://blog.csdn.net/lff0305/article/details/8277983

分享到:
评论

相关推荐

    hibernate3+ proxool-0.9.1配置 和proxool-0.9.1.jar

    标题中的“hibernate3+ proxool-0.9.1配置”涉及到的是在Java开发中,使用Hibernate3 ORM框架与Proxool连接池的整合配置。Hibernate3是一款流行的持久层框架,它允许开发者用面向对象的方式来操作数据库,而Proxool...

    proxool-0.9.1.jar,proxool-cglib.jar

    标题中的"proxool-0.9.1.jar"和"proxool-cglib.jar"是两个重要的Java档案文件,它们是Proxool项目的组件。Proxool是一个开源的数据库连接池解决方案,它允许开发者在Java应用程序中高效地管理数据库连接。数据库连接...

    proxool配置参数说明及proxool-0.9.1相关jar包及spring配置方法

    Spring框架中的DataSource配置使得Proxool的集成变得简单,而proxool-0.9.1.jar和proxool-cglib.jar是运行Proxool所需的核心库。在实际应用中,正确理解和配置这些参数以及库文件,可以优化数据库访问性能,提高系统...

    proxool 0.9.1 修复bug版

    修复了houseKeepingSleepTime maximumActiveTime 和 maximumConnectionLifetime 的类型long的set方法的bug

    proxool-0.9.1

    **Proxool 0.9.1:数据库连接池详解** `Proxool` 是一个开源的、基于Java的数据库连接池,它提供了一种高效、灵活的方式来管理和控制数据库连接。在0.9.1版本中,这个工具为开发者提供了更稳定的性能和优化的资源...

    proxool-0.9.1.jar proxool_cglib-0.9.1.jar

    标题中的"proxool-0.9.1.jar"和"proxool_cglib-0.9.1.jar"是两个Java库文件,它们是Proxool项目在0.9.1版本时的实现。Proxool是一个开源的数据库连接池,它提供了一种灵活且高效的解决方案来管理数据库连接。在Java...

    proxool-0.9.1.jar

    proxool-0.9.1.jar包是一个数据库连接池包,最新版解决前几个版本里在二次关闭一个rs集的时候警告等一些bug。proxool-0.9.1.jar监控在对中文监控出现乱码情况做了更改。具体是对org.logicalcobwebs.proxool.admin....

    struts2.2.3+spring2.5.6+hibernate3.2+proxool0.9.1

    Struts2.2.3、Spring2.5.6、Hibernate3.2和Proxool0.9.1是四个重要的Java技术组件,它们在Web应用程序开发中扮演着关键角色。这个压缩包文件包含了这些技术的集成示例,旨在帮助开发者理解和实践如何将它们有效地...

    proxool-0.9.1源码下载

    **Proxool源码分析** Proxool是一个开源的数据库连接池实现,它在Java环境中提供了高效的数据库连接管理。在0.9.1版本中,我们可以深入研究其内部机制,理解如何实现数据库连接的创建、管理和回收,以及如何优化...

    Hibernate3.5.1+Proxool0.9.1+Oracle10g2实现关键

    标题 "Hibernate3.5.1+Proxool0.9.1+Oracle10g2实现关键" 提供了一个关于整合三个技术的实践场景:Hibernate 3.5.1(一个流行的Java对象关系映射框架),Proxool 0.9.1(一个数据库连接池)以及Oracle 10g 2(一种...

    proxool-0.9.1-source

    "Proxool-0.9.1-source"是Proxool的一个特定版本的源代码包,主要用于数据库连接池管理。Proxool是一个开源的、基于Java的数据库连接池实现,它提供了一种灵活且可扩展的方式来管理和优化数据库连接。在这个0.9.1...

    proxool-0.9.1.2

    在上次修改的0.9.1.1基础上,再次修改一个bug 5.修正了ProxoolDataSource这个bean在spring配置中几个property不正确的问题。 houseKeepingSleepTime maximumConnectionLifetime overloadWithoutRefusalLifetime ...

    Proxool0.9.1的配置与应用[定义].pdf

    在0.9.1版本中,虽然有一些配置上的变动,但它仍然是一个常用的数据库连接池解决方案,尤其对于那些希望避免频繁创建和关闭数据库连接的项目。 配置Proxool主要涉及编辑`proxool.xml`文件,这个文件包含了所有关于...

    proxool-0.9.1.tar.gz

    `proxool-0.9.1.tar.gz` 是一个针对Java平台的开源数据库连接池实现,名为Proxool。在IT行业中,数据库连接池是一种重要的资源管理工具,它有效地管理和复用数据库连接,以提高应用性能,降低系统资源消耗。Proxool...

    proxool 0.9.1 修改

    解决在使用spring 配置 proxool 0.9.1时碰到‘houseKeepingSleepTime’is not writeable or has an invalid setter method的问题。 方法是将org.logicalcobwebs.proxool.ProxoolDataSource 中houseKeepingSleepTime...

    proxool-0.9.1.jar commons-logging.jar

    首先,`proxool-0.9.1.jar`是Proxool数据库连接池的实现库,它是一个开源的、轻量级的Java连接池解决方案。Proxool允许开发者在应用中使用多个数据库连接,并通过池化技术来减少创建和销毁数据库连接的开销。这个...

    proxool-0.9.1.zip

    标题中的"proxool-0.9.1.zip"是一个压缩包文件,其中包含了与Proxool相关的组件。Proxool是Java的一个开源数据库连接池,它允许开发者在应用程序中更有效地管理和控制数据库连接。这个0.9.1版本可能是Proxool的一个...

Global site tag (gtag.js) - Google Analytics