摘要:加載階段虛擬機規范中并沒有進行強制約束,這點可以交給虛擬機的具體實現來自由把握。由于這個類加載器是中的方法的返回值,所以一般也稱它為系統類加載器。如果父類加載失敗,拋出異常后,再調用自己的方法進行加載。
類從被加載到虛擬機內存中開始,到卸載出內存為止,它的整個生命周期包括:加載(Loading)、驗證(Verification)、準備(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸載(Unloading)7個階段。其中驗證、準備、解析3個部分統稱為連接(Linking)。
加載階段:
Java虛擬機規范中并沒有進行強制約束,這點可以交給虛擬機的具體實現來自由把握。
初始化時機:
5種情況下必須對類進行初始化
2.1 遇到new,getstatic,putstatic,invokestatic這4種字節碼指令時,如果類沒有進行初始化,那就必須對類進行初始化,比如說:new一個對象,訪問或設置static變量(final修飾的除外),調用類的靜態方法
2.2 使用java.lang.reflect包的方法對類進行反射調用的時候,如果類沒有進行過初始化,則需要先觸發其初始化。
2.3 當初始化一個類時,如果其父類還沒有初始化,需要先對父類進行初始化
2.4 當虛擬機啟動的時候,用戶的主類(包含main方法的那個類),虛擬機會初始化這個類
2.5 當使用JDK1.7的動態語言支持時,如果一個java.lang.invoke.MethodHandle實例最后的解析結果REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,并且這個方法句柄所對應的類沒有進行過初始化,則需要先觸發其初始化。
驗證是連接階段的第一步,這一階段的目的是為了確保Class文件的字節流中包含的信息符合當前虛擬機的要求,并且不會危害虛擬機自身的安全。
準備階段是正式為類變量分配內存并設置類變量初始值的階段,這些變量所使用的內存都將在方法區中進行分配。
解析階段是虛擬機將常量池內的符號引用替換為直接引用的過程,
符號引用(SymbolicReferences):符號引用以一組符號來描述所引用的目標,符號可以是任何形式的字面量,只要使用時能無歧義地定位到目標即可。符號引用與虛擬機實現的內存布局無關,引用的目標并不一定已經加載到內存中。各種虛擬機實現的內存布局可以各不相同,但是它們能接受的符號引用必須都是一致的,因為符號引用的字面量形式明確定義在Java虛擬機規范的Class文件格式中。
直接引用(DirectReferences):直接引用可以是直接指向目標的指針、相對偏移量或是一個能間接定位到目標的句柄。直接引用是和虛擬機實現的內存布局相關的,同一個符號引用在不同虛擬機實例上翻譯出來的直接引用一般不會相同。如果有了直接引用,那引用的目標必定已經在內存中存在。
初始化階段是執行類構造器<clinit>()方法的過程。
<clinit>()方法是由編譯器自動收集類中的所有類變量的賦值動作和靜態語句塊(static{}塊)中的語句合并產生的,編譯器收集的順序是由語句在源文件中出現的順序所決定的,靜態語句塊中只能訪問到定義在靜態語句塊之前的變量,定義在它之后的變量,在前面的靜態語句塊可以賦值,但是不能訪問。
類的加載器
啟動類加載器(BootstrapClassLoader):這個類將器負責將存放在<JAVA_HOME>lib目錄中的,或者被-Xbootclasspath參數所指定的路徑中的,并且是虛擬機識別的(僅按照文件名識別,如rt.jar,名字不符合的類庫即使放在lib目錄中也不會被加載)類庫加載到虛擬機內存中。
擴展類加載器(ExtensionClassLoader):這個加載器由sun.misc.Launcher$ExtClassLoader實現,它負責加載<JAVA_HOME>libext目錄中的,或者被java.ext.dirs系統變量所指定的路徑中的所有類庫,開發者可以直接使用擴展類加載器。
應用程序類加載器(ApplicationClassLoader):這個類加器由sun.misc.Launcher$App-ClassLoader實現。由于這個類加載器是ClassLoader中的getSystemClassLoader()方法的返回值,所以一般也稱它為系統類加載器。它負責加載用戶類路徑(ClassPath)上所指定的類庫,開發者可以直接使用這個類加載器,如果應用程序中沒有自定義過自己的類加載器,一般情況下這個就是程序中默認的類加載器。
雙親委派模型的工作過程是:如果一個類加載器收到了類加載的請求,它首先不會自己去嘗試加載這個類,而是把這個請求委派給父類加載器去完成,每一個層次的類加載器都是如此,因此所有的加載請求最終都應該傳送到頂層的啟動類加載器中,只有當父加載器反饋自己無法完成這個加載請求(它的搜索范圍中沒有找到所需的類)時,子加載器才會嘗試自己去加載。
先檢查是否已經被加載過,若沒有加載則調用父加載器的loadClass()方法,若父加載器為空則默認使用啟動類加載器作為父加載器。如果父類加載失敗,拋出ClassNotFoundException異常后,再調用自己的findClass()方法進行加載。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/69302.html
摘要:作用負責將加載到中審查每個類由誰加載父優先的等級加載機制將字節碼重新解析成統一要求的對象格式類結構分析為了更好的理解類的加載機制,我們來深入研究一下和他的方法。就算兩個是同一份字節碼,如果被兩個不同的實例所加載,也會認為它們是兩個不同。 申明:本文首發于 詳細深入分析 ClassLoader 工作機制 ,如有轉載,注明原出處即可,謝謝配合。 什么是 ClassLoader ? 大家...
摘要:前面提到,對于數組類來說,它并沒有對應的字節流,而是由虛擬機直接生成的。對于其他的類來說,虛擬機則需要借助類加載器來完成查找字節流的過程。驗證階段的目的,在于確保被加載類能夠滿足虛擬機的約束條件。 Java 虛擬機將字節流轉化為 Java 類的過程。這個過程可分為加載、鏈接以及初始化 三大步驟。 加載是指查找字節流,并且據此創建類的過程。加載需要借助類加載器,在 Java 虛擬機中,類...
摘要:如果需要支持類的動態加載或需要對編譯后的字節碼文件進行解密操作等,就需要與類加載器打交道了。雙親委派模型,雙親委派模型,約定類加載器的加載機制。任何之類的字節碼都無法調用方法,因為該方法只能在類加載的過程中由調用。 jvm系列 垃圾回收基礎 JVM的編譯策略 GC的三大基礎算法 GC的三大高級算法 GC策略的評價指標 JVM信息查看 GC通用日志解讀 jvm的card table數據...
摘要:新生代又被劃分為三個區域和兩個幸存區。這樣劃分的目的是為了使能夠更好地管理堆內存中的對象,包括內存的分配及回收。新生代主要存儲新創建的對象和尚未進入老年代的對象。 在Java中主要有以下三種類加載器: 引導類加載器(bootstrap class loader) --用來加載java的核心庫(Strin...
閱讀 3081·2021-11-24 10:47
閱讀 3831·2021-11-02 14:43
閱讀 2228·2021-09-26 10:15
閱讀 2253·2021-09-08 09:35
閱讀 560·2019-08-30 12:45
閱讀 2781·2019-08-29 17:04
閱讀 3214·2019-08-26 14:05
閱讀 1259·2019-08-26 12:10