您好,登錄后才能下訂單哦!
這篇文章主要為大家詳細介紹了JAVA虛擬機類加載機制,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
類加載機制是把類的數據從Class文件加載到內存,并對數據進行校驗,轉換解析和初始化,最終形成可以被虛擬機直接使用的java類型。這一系列的過程都是在程序運行期間完成的。
類加載器
類加載器就是下圖中紅框的部分,它通過一個類的全限定名來獲取描述此類的二進制字節流,從而將java類動態地加載進JVM的內存空間中。
適用情景
對于一個非數組類的加載階段,可以使用系統提供的引導類加載器來完成,也可以由用戶自定義的類加載器去完成。
對于數組類而言,其由java虛擬機直接創建,不通過類加載器。
雙親委派機制
雙親委派機制是類加載所采取的一種方式。如果一個類加載器收到了類加載的請求,它首先不會自己去嘗試加載這個類,而是把這個請求委派給父類加載器去完成。每一層的類加載器均是如此。只有當父加載器反饋自己無法完成這個請求時,子加載器才會嘗試自己去加載。
類比到現實:小明想買一個玩具挖土機,可他又不好意思直接張口說。所以,發生了下面的對話。
小明去問他爸爸:爸爸你有挖土機嗎?
爸爸說:沒有哎
接著爸爸問爺爺:爸爸爸爸,你有挖土機嗎?
爺爺說:沒有哎
接著爺爺問太爺爺:爸爸爸爸,你有挖土機嗎?
太爺爺說:我也沒有。讓重孫子去買一個吧。
結果小明就高高興興地自己去買了一個玩具挖土機。
分類
啟動類加載器是使用C++實現的,是虛擬機自身的一部分。
其它類加載器是由java語言實現的,獨立于虛擬機外部,并且全都繼承自抽象類java.lang.ClassLoader。
好處
以String類為例。就算是用戶自己寫了一個String類的實現,那對此類進行加載時,也只會委派給啟動類加載器來對JDK中原本的String類進行加載,而自定義的String類永遠不會被調用。這樣保證了系統的安全。
什么時候進行類加載?
有且只有以下5種方式必須立即對類進行加載
(1)使用new實例化對象的時候;讀取或配置一個類的靜態字段(被final修飾、已在編譯期把結果放入常量池的靜態字段除外)的時候;調用一個類的靜態方法的時候。
(2)使用java.lang.reflect包的方法對類進行反射調用的時候。如果類沒有進行過初始化,則需要先觸發其初始化。
(3)當初始化一個類的時候,如果發現其父類還沒有進行過初始化,則需要先觸發其父類的初始化。
(4)當虛擬機啟動時,用戶需要指定一個要執行的主類(包含main()方法的類),虛擬機會先初始化這個主類
類加載過程詳述
類加載過程分為5步。大部分都是由虛擬機主導和控制的,除了以下兩種情形:
在加載階段
開發人員可以通過自定義類加載器參與
在初始化階段
會執行開發人員的代碼去初始化類變量和其它資源
1、加載
虛擬機需要完成的事情:
(1) 通過一個類的全限定名來獲取定義此類的二進制字節流。
(2)將這個字節流所代表的靜態存儲結構轉化為方法區的運行時數據結構。
(3)在內存中生成一個代表這個類的java.lang.Class對象,作為方法區這個類的各種數據的訪問入口。
2、驗證
驗證的目的是確保Class文件的字節流中包含的信息符合當前虛擬機的要求,不會危害虛擬機自身的安全。
其分為4個步驟:文件格式驗證,元數據驗證,字節碼驗證,符號引用驗證。其中文件格式驗證是直接對字節流進行操作的,其余3項是在方法區中進行的。
3、準備
此階段是正式為類變量分配內存并設置類變量初始值的階段。其是在方法區中進行分配的。有兩個注意點:
(1)此時只是對類變量(被static修飾的變量)進行內存分配,而不是對象變量。給對象分配內存是在對象實例化時,隨著對象一起分配到java堆中。
(2)如果一個類變量沒有被final修飾,則其初始值是數據類型的零值。比如int類型的是0,boolean類型的是false。舉個例子來說明:
public static int value=123;
在準備階段過后的初始值為0而不是123,因為這個時候尚未開始執行任何java方法,而把value賦值為123的putstatic指令是程序被編譯后,存放于類構造器< clinit >()方法之中。所以把value賦值為123的動作將在初始化階段才會執行。
public static final int value=123;
此時因為有final,所以在準備階段value就已經被賦值為123了。
4、解析
解析階段是虛擬機將常量池內的符號引用替換為直接引用的過程。可對類或接口、字段、類方法、接口方法等進行解析。
符號引用是什么:
符號引用就是包含類的信息,方法名,方法參數等信息的字符串,它供實際使用時在該類的方法表中找到對應的方法。
直接引用是什么:
直接引用就是偏移量,通過偏移量可以直接在該類的內存區域中找到方法字節碼的起始位置。
符號引用是告訴你此方法的一些特征,你需要通過這些特征去尋找對應的方法。直接引用就是直接告訴你此方法在哪。
5、初始化
此階段用于初始化類變量和其它資源,是執行類構造器< clinit >()方法的過程,此時才是真正開始執行類中定義的java程序代碼。
以上就是JAVA虛擬機類加載機制介紹的詳細內容了,看完之后是否有所收獲呢?如果想了解更多相關內容,歡迎來億速云行業資訊!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。