从DB2连接出错来认识WebServer的原理

    最近因为写一个数据库连接池放在ServletContextListener中初始化N个连接,结果几个同事因为直接在WAS下作开发,经常有编译后的类会导致重启EAR,结果就在Listener的初始化DB2连接时报出"Navive Library **.dll loaded by another classloader.."的错,如此云云,追踪到代码中,确实Class.forName("COM.ibm.db2.jdbc.app.DB2Driver"),仅这一行代码来讲根本就无法找到错误的根源。于是无论是到网上摆渡一下还是问别人(有些人倒是打非所问的说用COM.ibm.db2.jdbc.net.DB2Driver不会出错,但显然这并不是在解决问题而是逃避问题),都是云里雾里的,被它翻来覆去的纠缠得不行。今天终于狠下决心,用我所熟悉的Tomcat来调试,嘿嘿,虽折腾了一会,总算是找到了问题之所在!高兴之余,不忘发表出来,期望大多数像我等这辈不会再被它困扰了。
    首先,从JDK的异常信息可以知道,原因是某个dll被重新加载,这也是两种DB2驱动的不同所在,那么为什么会加载两次(或更多)呢?是因为DriveManager 注册了一个驱动之后就不能再注册吗?如果是,那在Listener destoryed的时候将它deRegister不就OK吗?唉,可惜试验证明并不是它!那么是否重新部署一个WAR,它的classLoader变了而原先的ClassLoader还未销毁?通过Debug证明,ClassLoader始终是同一个!此时,幸好我还有另一个很干净的war,而用到的公用lib也是自己亲手写出来的,所以经过反复比较,发现在问题war中lib下包含db2java.jar等一系列驱动包,此时才真相大白:因为在tomcat的common/lib下,已经存在这些驱动程序包,那肯定是前后几次加载的驱动包不同(其实文件是完全一致、唯位置不同,而这正是ClassLoader的本质啊)。原因分析出了,立即动手,果然OK!
    接着冷静的分析Tomcat机制(其他WebServer应类比吧):在启动Tomcat的时候,它的classpath是common/lib,理应会加载db2java.jar,而ServletContextListener启动的时候WAR的lib还不可能找到,所以连库的时候用到的是common/lib下的包,但当restart一个war的时候,Classloader找的却是WAR的lib了,如此一来,dll可不就是被两个ClassLoader加载了?
    所以,当遇到奇怪现象的时候,请不要怀疑你的机器跟你捣乱,机器毕竟是机器,它只会机械地工作而决不会主动的走歪门邪道,只要它不工作了,必定是作为操作者的人在哪方面出现了遗漏,当从自身找答案。吃一堑长一智,但愿出现过的问题不会再出现吧!
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值