JVM:class載入時機及兩種顯示載入的區別
阿新 • • 發佈:2019-01-01
從下面程式碼可以看出來幾點:
1、 class檔案的載入的時機
顯示載入:
呼叫ClassLoader.loadClass(className)與Class.forName(className)
隱式載入:
建立類物件
使用類的靜態域
建立子類物件
使用子類的靜態域
注意其實還有其他特殊的隱式載入:
在JVM啟動時,BootStrapLoader會載入一些JVM自身執行所需的class
在JVM啟動時,ExtClassLoader會載入指定目錄下一些特殊的class
在JVM啟動時,AppClassLoader會載入classpath路徑下的class,以及main函式所在的類的class檔案。
2、 兩種顯示載入class檔案到JVM的區別
Class.forName(className)載入class的同時會初始化靜態域
ClassLoader.loadClass(className)則不會初始化靜態域
Class.forName藉助當前呼叫者的class的ClassLoader完成class的載入。
3、 class檔案的隱式載入會執行static域
4、 JVM預設的ClassLoader是AppClassLoader
=================================== 下面附上測試程式碼 =========================================
package jiq.basic;
class SuperClass
{
public static int i = 0;
public static void func(){}
static {System.out.println("靜態區域被執行!");}
}
class SubClass extends SuperClass
{
public static int j = 0;
}
public class Test
{
//僅僅只是作為引數或者變量出現不會載入對應的class檔案
SuperClass cc1 = null;
public static void TestClassLoader(SuperClass vv) throws ClassNotFoundException
{
/**
* 顯示載入class並初始化靜態域
* 將列印:靜態區域被執行!
*/
Class.forName("jiq.basic.SuperClass");
/**
* 隱式載入class並初始化靜態域
* 將列印:靜態區域被執行!
*/
SuperClass c = new SuperClass(); //使用關鍵字new建立物件
SuperClass.i = 9; //使用類的靜態欄位
SuperClass.func(); //使用類的靜態方法
new SubClass(); //使用關鍵字new建立子類物件
SubClass.j = 10; //使用子類的靜態域
/**
* 僅僅只是作為引數或者變量出現不會載入對應的class檔案
* 不會列印:靜態區域被執行!
*/
SuperClass cc = vv;
SuperClass array[] = new SuperClass[5];
/**
* 呼叫ClassLoader的loadClass方法只會載入class檔案到JVM
* 並不會初始化靜態區域,這就是ClassLoader.loadClass與Class.forName的區別
* 不會列印:靜態區域被執行!
*/
ClassLoader.getSystemClassLoader().loadClass("jiq.basic.SuperClass");
/**
* 輸出為 [email protected]
* 可以看出JVM預設的類載入器ClassLoader是AppClassLoader
* 而BootStrapClassLoader和ExtClassLoader都是相對較為特殊的ClassLoader
*/
System.out.println(ClassLoader.getSystemClassLoader());
}
public static void main(String[] args) throws ClassNotFoundException
{
TestClassLoader(null);
}
}