Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4486149
  • 博文数量: 192
  • 博客积分: 10014
  • 博客等级: 上将
  • 技术积分: 8232
  • 用 户 组: 普通用户
  • 注册时间: 2006-07-21 00:22
文章分类

全部博文(192)

文章存档

2011年(4)

2009年(14)

2008年(174)

我的朋友

分类:

2008-08-13 23:39:44

 
 

使用JDBC 2 driver在Tomcat中连接DB2 V7.2时,如果你的驱动包和Connection Pool包(假设有的话,例如dbcp)放在web app/WEB-INF/lib时,下面的情况们会出现莫名其妙的"No suitable driver"异常:
    a. 两个web app的话,在第一个使用Connection很正常,但是在第二个web app中使用的话就会有异常
    b. 一个web app被tomcat重新装载后

异常信息为
    Cannot create JDBC driver of class 'COM.ibm.db2.jdbc.app.DB2Driver' for connect URL 'jdbc:db2:xxx'.
    Caused by: java.sql.SQLException: No suitable driver

原因
   a. 不论是直接获取,还是通过DataSource来获取数据库连接,首次获取物理连接的方式是首先通过Class.forName(),接着通过DriverManager.getConnection()或者.getDriver()
   b. Class.forName()是使用当前class的ClassLoader来装载COM.ibm.db2.jdbc.app.DB2Driver这个类,DB2Driver在静态初始化的时候会创建一个DB2Driver实例
      DB2Driver在实例化时发现如果db2jdbc.dll被其他ClassLoader装载,就会抛出java.lang.UnsatisfiedLinkError: Native Library C:\Program Files\SQLLIB\bin\db2jdbc.dll already loaded in another classloader,
      这是最主要的错误原因,导致该DB2Driver不能注册到DriverManager中。DB2Driver不会抛出这个异常,而只是在DriverManager中打印出来,console中是看不到的。
      更重要的是,虽然DB2Driver被Web ClassLoader装载到JVM中,但是并没有注册到DriverManager,所以DriverManager只有一个DB2Driver,就是第一个WebClassLoader装载的Driver。
   c. 在DriverManager的Connection getConnection(String url, java.util.Properties info, ClassLoader callerCL)方法和Driver getDriver(String url)方法中,
      DriverManager要保证已经注册的driver的ClassLoader和当前调用这个两个方法的ClassLoader一致,否则抛出SQLException "No suitable driver"。
      (两个方法都是调用DriverManager的native方法ClassLoader getCallerClassLoader()获取调用者的ClassLoader,第一个方法的入参callerCL如果是null,则使用Thread.currentThread().getContextClassLoader().
      DriverManager是由Bootstrap ClassLoader装载,所以在tomcat进程中是singleton。)

  

   所以,同样的情况适用于所有的Application Server,而非只Tomcat。

解决方法
   将jdbc驱动包放在%CATALINA_HOME%/common/lib中,使得该驱动不会在各个web app共存,而是分享。(因为Tomcat的Common ClassLoader是会被各个web app分享的,详见tomcat文档)

   

要注意的问题
   a. 由于DriverManager在tomcat中是singleton,它保存了各个Driver,包括其class和ClassLoader。这样的话,当web app重启时,DriverManager并不会deRegister相关的Driver,
      从而导致内存泄漏。当ClassLoader装载的Class足够多时,泄漏的内存会比较大。一个简单的解决方案是把Driver的jar包都放在%CATALINA_HOME%/common/lib下

阅读(3521) | 评论(0) | 转发(0) |
0

上一篇:python读取注册表值

下一篇:vim+ctags+taglist

给主人留下些什么吧!~~