起因:今天一个aar包在测试环境中正常运行,使用soapui测试正常返回,在本地环境中运行则老是报数据库连接异常,经检查,是因为在运行时环境中缺少ojdbc相关的jar包引起的。
重新打了一个aar包,将ojdbc放入aar中即可正常运行。
这引起了我极大的兴趣,为什么同一个aar,测试环境中无需在aar中lib添加ojdbc即可正常运行?
最后在这里找到答案:
Java虚拟机类加载顺序 (如评论所言,将文中写的“system classloader”有点误导,应该改成“AppClassLoader”,更方便理解,即应用类加载器)
1.检测此Class是否载入过(即在cache中是否有此Class),如果有到8,如果没有到2
2.如果parent classloader不存在(没有parent,那parent一定是bootstrap classloader了),到4
3.请求parent classloader载入,如果成功到8,不成功到5
4.请求jvm从bootstrap classloader中载入,如果成功到8
5.寻找Class文件(从与此classloader相关的类路径中寻找)。如果找不到则到7.
6.从文件中载入Class,到8.
7.抛出ClassNotFoundException.
8.返回Class.
tomcat中class和jar的加载顺序
由ClassLoader的双亲委托模式加载机制我们可以知道,假设两个包名和类名完全相同的class文件不再同一个jar包,如果一个class文件已经被加载java虚拟机里了,那么后面的相同的class文件就不会被加载了。
于是分别做了以下测试:
oracle.jdbc.driver.OracleDriver od = new oracle.jdbc.driver.OracleDriver(); // OracleDriver od = new OracleDriver(); String dbpath = java.net.URLDecoder.decode(od.getClass().getProtectionDomain().getCodeSource().getLocation().toString(),"UTF-8"); CommLogger.printlog("OracleDriver path"+ od.getClass().getProtectionDomain().getCodeSource().getLocation()); CommLogger.printlog("dbpath "+dbpath);
得到OracleDriver类的路径。
1.在tomcat/lib下加入ojdbc.jar。
2.在axis2/WEB-INF/lib下加入ojdbc.jar。
3.在打包的aar中加入ojdbc.jar。
仅条件1,输出结果如下:
dbpath file:/C:/Program Files/Apache Software Foundation/Tomcat 7.0/lib/ojdbc14.jar
仅条件2,输出结果如下:
dbpath file:/C:/Program Files/Apache Software Foundation/Tomcat 7.0/webapps/axis2/WEB-INF/lib/ojdbc14.jar
仅条件3,输出结果如下:
dbpath file:/C:/Program Files/Apache Software Foundation/Tomcat 7.0/temp/axis2-tmp-8189257264145727421.tmp/axis24403210224279191362ojdbc14.jar
条件1和2,如下
dbpath file:/C:/Program Files/Apache Software Foundation/Tomcat 7.0/webapps/axis2/WEB-INF/lib/ojdbc14.jar
条件1和3,如下
dbpath file:/C:/Program Files/Apache Software Foundation/Tomcat 7.0/lib/ojdbc14.jar
条件2和3,如下
dbpath file:/C:/Program Files/Apache Software Foundation/Tomcat 7.0/webapps/axis2/WEB-INF/lib/ojdbc14.jar
条件123添加,如下
dbpath file:/C:/Program Files/Apache Software Foundation/Tomcat 7.0/webapps/axis2/WEB-INF/lib/ojdbc14.jar