--------背景-------
最近接手了一个网站修改的项目,04年写的,里面使用的技术比较老了,现在要修改里面的程序bug,关于JNDI连接池连接不释放的问题
--------问题内容-------
JNDI获取连接代码Context envContext = (Context) ctx.lookup("java:/comp/env");
                m_DataSource = (DataSource) envContext.lookup(m_sJNDIURL);
//部分代码省略
 System.out.println(m_DataSource.getClass());
            BasicDataSource bd = (BasicDataSource)m_DataSource;
程序打印的是  class org.apache.commons.dbcp.BasicDataSource
也就是说  m_DataSource 的实际类型就是BasicDataSource ,但是当我强制转化为BasicDataSource 的时候,就会抛出异常
java.lang.ClassCastException: org.apache.commons.dbcp.BasicDataSource这里不太理解为啥会强制转化错误???

解决方案 »

  1.   

    首先你要确定是不是命名都为org.apache.commons.dbcp.BasicDataSource,即包名是否一致
    还有一个可能是它们的ClassLoader不一样。
    你可以打印BasicDataSource.class.getClassLoader()和m_DataSource.getClass().getClassLoader()看看
      

  2.   

    首先根据提示我确认了一下包名是一致的。然后是判断ClassLoader,通过打印
    m_DataSource.getClass().getClassLoader() 的结果是 class org.apache.commons.dbcp.BasicDataSource
    BasicDataSource.class.getClassLoader()   的结果是
    StandardClassLoader
      delegate: true
      repositories:
        file:E:\service\tomcat5.0\common\classes\
        file:E:\service\tomcat5.0\common\lib\ant-launcher.jar
        file:E:\service\tomcat5.0\common\lib\ant.jar
        file:E:\service\tomcat5.0\common\lib\classes12.jar
        file:E:\service\tomcat5.0\common\lib\commons-collections-3.1.jar
        file:E:\service\tomcat5.0\common\lib\commons-dbcp-1.2.1.jar
        file:E:\service\tomcat5.0\common\lib\commons-el.jar
        file:E:\service\tomcat5.0\common\lib\commons-pool-1.2.jar
        file:E:\service\tomcat5.0\common\lib\jasper-compiler.jar
        file:E:\service\tomcat5.0\common\lib\jasper-runtime.jar
        file:E:\service\tomcat5.0\common\lib\jsp-api.jar
        file:E:\service\tomcat5.0\common\lib\naming-common.jar
        file:E:\service\tomcat5.0\common\lib\naming-factory.jar
        file:E:\service\tomcat5.0\common\lib\naming-java.jar
        file:E:\service\tomcat5.0\common\lib\naming-resources.jar
        file:E:\service\tomcat5.0\common\lib\servlet-api.jar

    ----------> Parent Classloader:
    sun.misc.Launcher$AppClassLoader@15601ea
    其中我表明的红色部分是中间件tomcat5.0目录下的lib目录下的所以包的路径,通过这里的不同可以说明什么?还是不太明白
      

  3.   

    JNDI里用的是javax.sql.DataSource,
    和org.apache.commons.dbcp.BasicDataSource完全不相干,
    但它们都有一个getConnection()方法,用来获得数据库连接。
      

  4.   

    完全不相干是不对的,请看BasicDataSource的声明
    public class BasicDataSource
        implements DataSource
    BasicDataSource 是DataSource 的实现类,DataSource是一个接口,他并没有实现getConnection()方法的
      

  5.   

    m_DataSource.getClass().getClassLoader() 的结果是 class org.apache.commons.dbcp.BasicDataSource
    ---
    这个是绝对不可能的,打印一定是一个ClassLoader!从下面的打印看BasicDataSource是在Tomcat的Common中加载到的,要看你m_DataSource.getClass().getClassLoader()是否一样才知道原因
      

  6.   

    不过上面说得对,其实我不明白你为什么要转化成BasicDataSource正常来说转换成
    DataSource ds = (DataSource)envContext.lookup(m_sJNDIURL);
    ds.getConnection()应该就足够了,除非你真的需要BasicDataSource中而不在DataSource中的方法
      

  7.   

    如果是获取连接的话DataSource确实是足够了,但是我想得到现在连接池中正在使用的连接数,这就需要用到BasicDataSource中的一个getNumActive方法
      

  8.   

    SORRY,这里确实是我的疏忽了,我所说的打印确实是错误的,m_DataSource.getClass().getClassLoader()打印的是StandardClassLoader
      delegate: true
      repositories:
        file:E:\service\tomcat5.0\common\classes\
        file:E:\service\tomcat5.0\common\lib\ant-launcher.jar
        file:E:\service\tomcat5.0\common\lib\ant.jar
        file:E:\service\tomcat5.0\common\lib\classes12.jar
        file:E:\service\tomcat5.0\common\lib\commons-collections-3.1.jar
        file:E:\service\tomcat5.0\common\lib\commons-dbcp-1.2.1.jar
        file:E:\service\tomcat5.0\common\lib\commons-el.jar
        file:E:\service\tomcat5.0\common\lib\commons-pool-1.2.jar
        file:E:\service\tomcat5.0\common\lib\jasper-compiler.jar
        file:E:\service\tomcat5.0\common\lib\jasper-runtime.jar
        file:E:\service\tomcat5.0\common\lib\jsp-api.jar
        file:E:\service\tomcat5.0\common\lib\naming-common.jar
        file:E:\service\tomcat5.0\common\lib\naming-factory.jar
        file:E:\service\tomcat5.0\common\lib\naming-java.jar
        file:E:\service\tomcat5.0\common\lib\naming-resources.jar
        file:E:\service\tomcat5.0\common\lib\servlet-api.jar
    ----------> Parent Classloader:
    sun.misc.Launcher$AppClassLoader@15601ea
      

  9.   

    更正上面所说的BasicDataSource.class.getClassLoader() 的打印结果WebappClassLoader
      delegate: false
      repositories:
        /WEB-INF/classes/
    ----------> Parent Classloader:
    StandardClassLoader
      delegate: true
      repositories:
        file:E:\service\tomcat5.0\shared\classes\
    ----------> Parent Classloader:
    StandardClassLoader
      delegate: true
      repositories:
        file:E:\service\tomcat5.0\common\classes\
        file:E:\service\tomcat5.0\common\lib\ant-launcher.jar
        file:E:\service\tomcat5.0\common\lib\ant.jar
        file:E:\service\tomcat5.0\common\lib\classes12.jar
        file:E:\service\tomcat5.0\common\lib\commons-collections-3.1.jar
        file:E:\service\tomcat5.0\common\lib\commons-dbcp-1.2.1.jar
        file:E:\service\tomcat5.0\common\lib\commons-el.jar
        file:E:\service\tomcat5.0\common\lib\commons-pool-1.2.jar
        file:E:\service\tomcat5.0\common\lib\jasper-compiler.jar
        file:E:\service\tomcat5.0\common\lib\jasper-runtime.jar
        file:E:\service\tomcat5.0\common\lib\jsp-api.jar
        file:E:\service\tomcat5.0\common\lib\naming-common.jar
        file:E:\service\tomcat5.0\common\lib\naming-factory.jar
        file:E:\service\tomcat5.0\common\lib\naming-java.jar
        file:E:\service\tomcat5.0\common\lib\naming-resources.jar
        file:E:\service\tomcat5.0\common\lib\servlet-api.jar
    ----------> Parent Classloader:
    sun.misc.Launcher$AppClassLoader@15601ea
      

  10.   

    从日志就知道他们两者的ClassLoader不一样,简单一点的办法就是修改启动文件,使得BasicDataSource在系统的classpath上
    如果你不想,那没有好办法了。使用反射吧m_DataSource.getClass().getMethod...这样