Java 虛擬機器之四:Java類載入機制
一:前言
Java語言的型別可以分為兩大類:基本型別和引用型別。
基本型別 包括byte,short,int,long,float,double,boolean,char。
引用型別 包括類,介面,陣列類和泛型引數。由於泛型引數會在編譯過程中被擦除,因此Java虛擬機器實際上只有前三種。在類,介面和陣列類中,陣列類是由Java虛擬機器直接生成的,其它兩種則有對應的位元組流。
二:載入
1.載入,就是查詢位元組流,並且據此生成一個代表這個類的java.lang.Class物件的過程。注意這裡位元組流不一定非得要從一個Class檔案獲取,這裡既可以從ZIP包中讀取(比如從jar包和war包中讀取),也可以在執行時計算生成(動態代理),也可以由其它檔案生成(比如將JSP檔案轉換成對應的Class類)。載入的資訊儲存在JVM的方法區。
2.對於陣列類來說,它並沒有對應的位元組流,而是由Java虛擬機器直接生成的。對於其它的類來說,Java虛擬機器則需要藉助類載入器來完成查詢位元組流的過程。
3.類載入器有兩種,一種是啟動類載入器,其它的類載入器都是java.lang.ClassLoader的子類。啟動類載入器是由C++實現的,沒有對應的Java物件,因此在Java中只能用null代替。除了啟動類載入器之外,另外兩個重要的類載入器是擴充套件類載入器和應用類載入器,均由Java核心類庫提供。 啟動類載入器載入最為基礎,最為重要的類,如JRE的lib目錄下jar包中的類;擴充套件類載入器的父類是啟動類載入器,它負責載入相對次要,但又通用的類,如JRE的lib/ext目錄下jar包中的類;應用類載入器的父類載入器則是擴充套件類載入器,它負責載入應用程式路徑下的類。
4.JVM透過雙親委派模型進行類的載入,當然我們也可以透過繼承java.lang.ClassLoader實現自定義的類載入器。當一個類載入器收到類載入任務,會先交給其父類載入器去完成,因此最終載入任務都會傳遞到頂層的啟動類載入器,只有當父類載入器無法完成載入任務時,才會嘗試執行載入任務。
採用雙親委派的一個好處是比如載入位於rt.jar包中的類java.lang.Object,不管是哪個載入器載入這個類,最終都是委託給頂層的啟動類載入器進行載入,這樣就保證了使用不同的類載入器最終得到的都是同樣一個Object物件。
三:連結
連結,是指將建立成的類合併至Java虛擬機器中,使之能夠執行的過程。它分為驗證,準備和解析三個階段。
1.驗證
該階段的目的在於確保被載入類能夠滿足Java虛擬機器的約束條件。
2.準備
該階段的目的是為被載入類的靜態欄位分配記憶體,即在方法區中分配這些變數所使用的記憶體空間。Java程式碼中對靜態欄位的具體初始化,則會在稍後的初始化階段中進行。
3.解析
在class檔案被載入至Java虛擬機器前,這個類無法知道其它類及其方法,欄位所對應的具體地址。甚至不知道自己方法,欄位的地址。因此,每當需要引用這些成員時,
Java編譯器會生成一個符號引用。在執行階段,這個符號引用一般能夠無歧義地定位到具體目標上。解析階段的目的,正是將這些符號引用解析為實際引用。如果符號引用
指向一個未被載入的類,或者未被載入類的欄位或方法,那麼解析將觸發這個類的載入。
四:初始化
1.初始化階段是類載入最後一個階段,前面的類載入階段之後,除了在載入階段可以自定義類載入器以外,其它操作都由JVM主導。到了初始階段,才開始真正執行類中定義的Java程式程式碼。
2.在 Java 程式碼中,如果要初始化一個靜態欄位,我們可以在宣告時直接賦值,也可以在靜態程式碼塊中對其賦值。
如果直接賦值的靜態欄位被 final 所修飾,並且它的型別是基本型別或字串時,那麼該欄位便會被 Java 編譯器標記成常量值(ConstantValue),其初始化直接由 Java 虛擬機器完成。除此之外的直接賦值操作,以及所有靜態程式碼塊中的程式碼,則會被 Java 編譯器置於同一方法中,並把它命名為 < clinit >。
類載入的最後一步是初始化,便是為標記為常量值的欄位賦值,以及執行 < clinit > 方法的過程。Java 虛擬機器會透過加鎖來確保類的 < clinit > 方法僅被執行一次。
只有當初始化完成之後,類才正式成為可執行的狀態。
3.JVM 規範列舉類的初始化被觸發的情況:
a.當虛擬機器啟動時,初始化使用者指定的主類;
b.當遇到用以新建目標類例項的 new 指令時,初始化 new 指令的目標類;
c.當遇到呼叫靜態方法的指令時,初始化該靜態方法所在的類;
d.當遇到訪問靜態欄位的指令時,初始化該靜態欄位所在的類;
e.子類的初始化會觸發父類的初始化;
f.如果一個介面定義了 default 方法,那麼直接實現或者間接實現該介面的類的初始化,會觸發該介面的初始化;
j.使用反射 API 對某個類進行反射呼叫時,初始化這個類;
h.當初次呼叫 MethodHandle 例項時,初始化該 MethodHandle 指向的方法所在的類。
五:總結
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28624388/viewspace-2213484/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- java虛擬機器類載入機制Java虛擬機
- Java 虛擬機器類載入機制Java虛擬機
- Java虛擬機器9:Java類載入機制Java虛擬機
- Java虛擬機器(六):類載入機制Java虛擬機
- Java虛擬機器 —— 類的載入機制Java虛擬機
- JVM(三)-java虛擬機器類載入機制JVMJava虛擬機
- 深入java虛擬機器學習–類的載入機制(四)Java虛擬機機器學習
- 深入理解Java虛擬機器(類載入機制)Java虛擬機
- 【Java虛擬機器規範】JVM類載入機制Java虛擬機JVM
- 深入理解Java虛擬機器 - 類載入機制Java虛擬機
- 深入理解Java虛擬機器 --- 類載入機制Java虛擬機
- 深入理解虛擬機器之虛擬機器類載入機制虛擬機
- 虛擬機器類載入機制虛擬機
- Java虛擬機器10:類載入器Java虛擬機
- 虛擬機器類載入機制:類載入時機虛擬機
- JVM(7)-虛擬機器類載入機制JVM虛擬機
- JVM(五)----虛擬機器類載入機制JVM虛擬機
- 虛擬機器系列 | JVM類載入機制虛擬機JVM
- 虛擬機器類載入機制_類載入的過程虛擬機
- 面試官,不要再問我“Java虛擬機器類載入機制”了面試Java虛擬機
- Java 虛擬機器類載入機制和位元組碼執行引擎Java虛擬機
- Java虛擬機器類載入的過程Java虛擬機
- 《深入理解java虛擬機器》第七章讀書筆記——虛擬機器類載入機制Java虛擬機筆記
- JVM學習-虛擬機器類載入機制JVM虛擬機
- Android虛擬機器框架:類載入機制Android虛擬機框架
- 【進階之路】深入理解Java虛擬機器的類載入機制(長文)Java虛擬機
- 《深入理解java虛擬機器》學習筆記6——類載入機制Java虛擬機筆記
- Java 類載入器以及載入機制Java
- 虛擬機器類載入機制_類載入時機和類的生命週期虛擬機
- 深入理解JVM,虛擬機器類載入機制JVM虛擬機
- 深入淺出JVM(三)之HotSpot虛擬機器類載入機制JVMHotSpot虛擬機
- java類載入機制Java
- Java虛擬機器系列之垃圾回收機制(2)Java虛擬機
- Java虛擬機器 —— 垃圾回收機制Java虛擬機
- Java 技術之類載入機制Java
- Java基礎-類載入器以及載入機制Java
- (深入理解 Java虛擬機器)一篇文章帶你深入瞭解Java 虛擬機器類載入器Java虛擬機
- Java面試題之Java類載入機制詳解!Java面試題