起因:今天一個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