JVM把描述類的數據從class文件加載到內存,並對數據進行校驗,解析和初始化,最終形成可以被虛擬機直接使用的Java類型,這就是JVM的類加載機制。
在加載階段虛擬機需要完成以下三件事:
1)通過一個類的全限定名稱來獲取此類的二進制字節流,並加載到內存中(需要使用類加載器)
2)將這個字節流所代表的靜態存儲結構轉化為方法區的運行時數據結構
3)在堆中生成一個代表這個類的java.lang.Class對象,作為方法區這個類的各種數據的訪問入口(所以反射通過類對象可以訪問到字段)
類加載機制為雙親委派模型,具體步驟如下:
如果一個類加載器收到了類加載請求,它首先不會自己去嘗試加載這個類,而是把類加載請求委派給父類加載器去完成。
每一層的類加載器都把類加載請求委派給父類加載器,依次向上,直到所有的類加載請求都傳遞給頂層的啟動類加載器。
如果頂層的啟動類加載器無法完成加載請求,子類加載器才會嘗試自己去加載該類,如果連最初發起類加載請求的類加載器也無法完成加載請求時,將會拋出ClassNotFoundException,而不再調用其子類加載器去進行類加載。
雙親委派模式的類加載機制的優點:
不同層次的類加載器具有不同優先級,比如所有Java對象的超級父類java.lang.Object,位於rt.jar中,無論哪個類加載器加載該類,最終都是由啟動類加載器進行加載,保證安全。即使用戶自己編寫一個java.lang.Object類並放入程序中,雖能正常編譯,但不會被加載運行,因為Java中的java.lang.Object類是由啟動類加載器進行加載,自己編寫的java.lang.Object類不會被啟動類加載器進行加載,保證不會出現混亂。相反,如果沒有雙親委派模型而是由各個類加載器自行加載的話,如果用戶編寫了一個java.lang.Object的同名類並放在ClassPath中,那系統中將會出現多個不同的Object類,程序將混亂。