PHP中文网2017-04-18 10:51:58
並不是全部加載,可以理解為按需加載。
例如繼承的父類,實現的接口,聲明的變量,方法的返回類型等。
就是在使用目前的類別時,缺少哪些必要的類別都會立即載入。
天蓬老师2017-04-18 10:51:58
按需加載。
類別載入的時機:
1)遇到new、getstatic、putstatic或invokestatic這4條字節碼指令時,如果類別沒有進行過初始化,則需要先觸發其初始化。產生這4個指令的最常見的Java程式碼場景是:使用new關鍵字實例化物件的時候、讀取或設定一個類別的靜態欄位(被final修飾、已在編譯期間將結果放入常數池的靜態字段除外)的時候,以及呼叫一個類別的靜態方法的時候。
2)使用java.lang.reflect套件的方法對類別進行反射呼叫的時候,如果類別沒有進行過初始化,則需要先觸發其初始化。
3)當初始化一個類別的時候,如果發現其父類別還沒有進行過初始化,則需要先觸發其父類別的初始化。
4)當虛擬機器啟動時,使用者需要指定一個要執行的主類別(包含main()方法的那個類別),虛擬機會先初始化這個主類別。
5)當使用JDK 1.7的動態語言支援時,如果一個java.lang.invoke.MethodHandle實例最後的解析結果REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,並且這個方法句柄所對應的類別沒有進行過初始化,則需要先觸發其初始化。
對於這5種會觸發類別進行初始化的場景,虛擬機器規範中使用了一個很強烈的限定語:“有且只有”,這5種場景中的行為稱為對一個類別進行主動引用。除此之外,所有引用類別的方式都不會觸發初始化,稱為被動引用。
來源:深入理解JVM 7.2 類別載入的時機
巴扎黑2017-04-18 10:51:58
這一塊還沒深入了解,不敢誤人子弟。
我知道的,虛擬機器在運作的時候,會預先載入一個常用的class,像是java.lang套件下面的。
至於你在程式中自己引用的class檔案/jar套件之類的,是有一個載入過程的。
當虛擬機器需要一個class文件,他會呼叫預設的classLoader.loadClass()去加載,這個方法首先在已經加載的class中查找,找得到當然返回,找不到則交給父加載器。層層查找沒有之後,classLoader會呼叫findClass方法去檔案中載入。
protected Class> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
c = findClass(name);
// this is the defining class loader; record the stats
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}