深刻Java虛擬機,ClassLoader是其中重要的一個環節。看書+查資料+動手,整理出以下要點:java
- Class loader using following four steps: a, Bootstrap ClassLoader/啓動類加載器 主要負責jdkhome/lib目錄下的核心 api 或 -Xbootclasspath 選項指定的jar包裝入工做. b, Extension ClassLoader/擴展類加載器 主要負責jdkhome/lib/ext目錄下的jar包或 -Djava.ext.dirs 指定目錄下的jar包裝入工做 c, System ClassLoader/系統類加載器 主要負責java -classpath/-Djava.class.path所指的目錄下的類與jar包裝入工做. b, User Custom ClassLoader/用戶自定義類加載器(java.lang.ClassLoader的子類)在程序運行期間, 經過java.lang.ClassLoader的子類動態加載class文件, 體現java動態實時類裝入特性. 加載順序是:自底向上檢查類是否已經裝在,有則返回,不然自頂向下嘗試加載類。
- 類裝入的方式有兩種 —— 顯式 或 隱式,二者之間有些細微差別。顯式 類裝入發生在使用如下方法調用裝入的類的時候: cl.loadClass()(cl 是 java.lang.ClassLoader 的實例) Class.forName()(啓動的類裝入器是當前類定義的類裝入器) 隱式 類裝入發生在因爲引用、實例化或繼承致使裝入類的時候(不是經過顯式方法調用)。在每種狀況下,裝入都是在幕後啓動的,JVM 會解析必要的引用並裝入類。與顯式類裝入同樣,若是類已經裝入了,那麼只是返回一個引用;不然,裝入器會經過委託模型裝入類。
- 項目源碼與jar中存在同包名同類名的類,運行時加載源碼中該類緣由:他們都屬於User classes,由系統類加載器加載。加載的時候搜索路徑順序: a. 缺省值:調用java或javaw的當前路徑,是項目class所在目錄 b. 環境變量classpath設置的路徑 c. 執行Java命令行-classpath或-cp的值。若是指定了這兩個命令行參數之一,它的值會覆蓋環境變量CLASSPATH的值。 d. -jar 選項:若是經過java -jar 來運行一個可執行的jar包,這當前jar包會覆蓋上面全部的值.換句話說,-jar 後面所跟的jar包的優先級別最高,若是指定了-jar選項,全部環境變量和命令行制定的搜索路徑都將被忽略.JVM APPClassloader將只會以jar包爲搜索範圍. 有關可執行jar有許多相關的安全方面的描述,能夠參考http://java.sun.com/docs/books/tutorial/jar/ 來全面瞭解. 這也是爲何應用程序打包成可執行的jar包後,無論你怎麼設置classpath都不能引用到第三方jar包的東西了.
另附ClassLoader.loadClass與Class.forName的區別,主要在因而否初始化:api
public class Test {
public static void main(String[] argv) throws ClassNotFoundException,
InstantiationException, IllegalAccessException {
// Class classT = ClassLoader.getSystemClassLoader().loadClass("Ti"); //not print static
// Class classT = Class.forName("Ti"); //print static
// Class classT = Class.forName("Ti", true, ClassLoader.getSystemClassLoader()); //print static
Class classT = Class.forName("Ti", false, ClassLoader.getSystemClassLoader()); // not print static
}
}
class Ti {
static {
System.out.println("static");
}
}
from: https://yq.aliyun.com/articles/27110?spm=5176.100239.blogcont7241.38.db8GKF