JVM 類加載機制分爲五個部分:加載,驗證,準備,解析,初始化,下面咱們就分別來看一下這五個過程。java
加載是類加載過程當中的一個階段,這個階段虛擬機要完成3件事。面試
這一階段的主要目的是爲了確保 Class 文件的字節流中包含的信息是否符合當前虛擬機的要求,而且不會危害虛擬機自身的安全。驗證主要包含4個階段的校驗動做:文件格式驗證、元數據驗證、字節碼驗證、符號引用驗證。安全
準備階段是正式爲類變量分配內存並設置類變量的初始值階段,即在方法區中分配這些變量所使用的內存空間。注意這裏所說的初始值概念,好比一個類變量定義爲:微信
public static int value = 123;
實際上變量 value 在準備階段事後的初始值爲 0 而不是 123,將 value 賦值爲 123 的 putstatic 指令是程序被編譯後,存放於類構造器方法之中。
可是注意若是聲明爲:數據結構
public static final int value = 123;
在編譯階段會爲 value 生成 ConstantValue 屬性,在準備階段虛擬機會根據 ConstantValue 屬性將 value 賦值爲 123。app
解析階段是指虛擬機將常量池中的符號引用替換爲直接引用的過程。符號引用就是在 class 文件中以: CONSTANT_Class_info、CONSTANT_Field_info
、CONSTANT_Method_info等類型的常量出現。spa
初始化階段是類加載最後一個階段,前面的類加載階段以後,除了在加載階段能夠自定義類加載器之外,其它操做都由 JVM 主導。到了初始階段,纔開始真正執行類中定義的 Java 程序代碼。代理
那麼,何時開始初始化?code
以上狀況稱爲對一個類進行主動引用,且有且只要以上幾種狀況須要對類進行初始化。orm
當使用 Java 命令運行 Java 程序時,此時 JVM 啓動,並去方法區下找 Java 命令後面跟的類是否存在,若是不存在,則把類加載到方法區下(還記得運行時數據區域裏的方法區嗎?)
在類加載到方法區時,會分爲兩部分:
上邊這兩部分歸納爲以下五步:
巴拉巴拉,一堆理論,不夠形象,補張圖
以下是一道真實的面試題,但願上文的理論部分對你有所幫助!
class Singleton{
private static Singleton singleton = new Singleton();
public static int value1;
public static int value2 = 0;
private Singleton(){
value1++;
value2++;
}
public static Singleton getInstance(){
return singleton;
}
}
class Singleton2{
public static int value1;
public static int value2 = 0;
private static Singleton2 singleton2 = new Singleton2();
private Singleton2(){
value1++;
value2++;
}
public static Singleton2 getInstance2(){
return singleton2;
}
}
public static void main(String[] args) {
Singleton singleton = Singleton.getInstance();
System.out.println("Singleton1 value1:" + singleton.value1);
System.out.println("Singleton1 value2:" + singleton.value2);
Singleton2 singleton2 = Singleton2.getInstance2();
System.out.println("Singleton2 value1:" + singleton2.value1);
System.out.println("Singleton2 value2:" + singleton2.value2);
}
說出運行的結果:
Singleton1 value1 : 1
Singleton1 value2 : 0
Singleton2 value1 : 1
Singleton2 value2 : 1
若是文章有錯的地方歡迎指正,你們互相留言交流。習慣在微信看技術文章,想要獲取更多的Java資源的同窗,能夠關注微信公衆號:niceyoo