您好,登錄后才能下訂單哦!
這篇文章主要介紹“Java類加載機制有哪些內容”,在日常操作中,相信很多人在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 指向的方法所在的類。
到此,關于“Java類加載機制有哪些內容”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。