wordpress 插件被墻免費seo工具
目錄
前言
1.什么是類加載?
2.類加載整體流程
3.一個類什么時候被加載?
4.雙親委派模型
4.1 JVM默認提供了三個類加載器
4.1.1 BootstrapClassLoader
4.1.2 ExtensionClassLoader
4.1.3 ApplicationClassLoader
4.2 破壞雙親委派模型
前言
在上一篇文章中,我們主要簡述了JVM內(nèi)存區(qū)域劃分的相關(guān)知識,下面我們將講述JVM類加載機制
1.什么是類加載?
? ? ? ? 類加載就是.class文件(.java通過javac進行編譯成class文件),從文件(硬盤)被加載到內(nèi)存中(元數(shù)據(jù)區(qū))的過程。
2.類加載整體流程
- 1.加載:把.class文件找到,打開文件,讀文件,把文件內(nèi)容讀到內(nèi)存中;
- 2.驗證:檢查下.class文件格式是否規(guī)范;
- 3.準備:給類對象分配內(nèi)存空間(先在元數(shù)據(jù)占個位置),也使靜態(tài)成員被設置成0;
- 4.解析:初始化字符串常量,把符號引用轉(zhuǎn)為直接引用。初始化字符串常量時,首先需要為字符的實際內(nèi)容分配一塊內(nèi)存空間,并確保有一個引用指向這塊內(nèi)存空間的起始地址。在類加載之前,字符串常量存在于.class文件中,這個"引用"記錄的是它在文件中的偏移量(占位符),而不是字符串常量的真正地址。當類加載完成后,字符串常量才會被放入內(nèi)存中,此時引用會被賦值為實際的內(nèi)存地址。
- 舉例:假設你得到了一張古老的藏寶圖,這張藏寶圖標記了一處隱藏的寶藏位置。這個過程與字符串常量的處理有類似之處:
-
1. 藏寶圖的研究(類加載前):在開始挖掘?qū)毑刂?#xff0c;藏寶圖就像是一個.class文件里的字符串常量。你知道這張圖代表了什么,但還沒有實際的行動。圖中標記的位置不是真實的地址,而是告訴你寶藏可能在哪里的一種“偏移量”或線索;
-
2. 準備挖掘(類加載):決定根據(jù)藏寶圖去探險,就好比是類加載的過程。你開始準備必要的工具,如鏟子和地圖,這相當于JVM為字符串常量分配內(nèi)存空間;
-
3. 定位寶藏(引用轉(zhuǎn)換):出發(fā)后,你按照藏寶圖上的線索前進,這如同符號引用被轉(zhuǎn)換為直接引用。你通過解讀地圖上的線索(可能是一棵樹、一塊石頭或一個特定形狀的地標),逐步接近寶藏的實際位置。
-
4. 挖掘?qū)毑?#xff08;訪問地址):當你到達指定地點并開始挖掘時,這就像是JVM訪問字符串常量在內(nèi)存中的實際位置。你挖出寶藏的那一刻,就類似于程序最終使用到這個字符串常量的內(nèi)容。
通過這個例子,我們可以看到,藏寶圖的使用過程(從解讀到實際挖掘出寶藏)與JVM如何處理字符串常量(從類加載到實際使用字符串內(nèi)容)有著相似的步驟。都是先有一個初步的指引(無論是藏寶圖還是符號引用),然后通過一系列的動作(解讀和應用),最終達到目的(找到寶藏或獲取字符串內(nèi)容)。
- 5.初始化:調(diào)用構(gòu)造方法,進行成員初始化,執(zhí)行代碼塊,靜態(tài)代碼塊,加載父類等。
3.一個類什么時候被加載?
- 首先我們要知道,不是Java程序一運行,就把所有的類都加載,而是真正用到才加載(懶漢模式),一旦加載過后,后續(xù)無需再重復加載;
- 加載的內(nèi)容有:
- 1.構(gòu)造類的實例;
- 2.調(diào)用這個類的靜態(tài)方法/使用靜態(tài)屬性;
- 3.加載子類,就會先加載其父類
4.雙親委派模型
在上面的類加載的整體流程中,我們說到了加載,
加載:把.class文件找到,打開文件,讀文件,把文件內(nèi)容讀到內(nèi)存中
- 雙親委派模型描述了類加載器在查找和加載.class文件時的基本過程。
-
4.1 JVM默認提供了三個類加載器
-
4.1.1 BootstrapClassLoader
- 負責加載標準庫的類
- (Java規(guī)范,要求提供哪些類)無論是哪種JVM的實現(xiàn),都會提供這些一樣的類
- 負責加載標準庫的類
-
4.1.2 ExtensionClassLoader
- 負責加載JVM擴展庫中的類
- (規(guī)范之外,由實現(xiàn)JVM的廠商/組織,提供的額外的功能)
- 負責加載JVM擴展庫中的類
-
4.1.3 ApplicationClassLoader
- 負責加載用戶提供的第三方庫/用戶項目代碼中的類
- 上述的三個類存在"父子關(guān)系",相當于每個class loader有一個parent屬性,指向自己的父 類加載器
- 4.1.4 上述的類加載器如何配合工作?
- 1.首先,類加載過程是從ApplicationClassLoader開始的。然而,ApplicationClassLoader不會直接進行加載,而是將加載任務委托給自己的父 類加載器。接下來,ExtensionClassLoader接收到委托后,同樣不會立即加載,而是再次將自己作為父類加載器,并將加載任務委托給它的父 類加載器BootstrapClassLoader。BootstrapClassLoader在收到委托時,發(fā)現(xiàn)自己沒有父類加載器(即父類為null),于是它自己執(zhí)行實際的加載操作。
- 2.BootstrapClassLoader會搜索自己負責的標準庫目錄,尋找相關(guān)的類。如果找到了目標類,則進行加載;如果沒有找到,它會將加載任務委托給子類加載器。ExtensionClassLoader會真正地搜索擴展庫相關(guān)的目錄,同樣地,如果找到了目標類,則進行加載;如果沒有找到,它也會將加載任務委托給子類加載器。ApplicationClassLoader則會搜索用戶相關(guān)的目錄,如果找到了目標類,則進行加載;如果沒有找到,由于此時已經(jīng)沒有其他子類加載器了,所以只能拋出一個類找不到的異常。
- 3.為什么要有上述順序?
- 上述這套順序?qū)嶋H上是由JVM實現(xiàn)代碼的邏輯所決定的,這種邏輯類似于遞歸的方式;
- 主要目的是確保Bootstrap能夠優(yōu)先加載,而Application能夠稍后加載,以避免用戶創(chuàng)建一些奇怪的類,從而引發(fā)不必要的bug;
- 在一方面,類加載器可以由用戶自定義。除了JVM自帶的Bootstrap ClassLoader、Extension ClassLoader和Application ClassLoader之外,用戶可以創(chuàng)建自己的類加載器,并將其加入到類加載流程中。這樣,用戶可以根據(jù)自己的需求決定加載順序,并且可以與現(xiàn)有的加載器配合使用。
-
4.2 破壞雙親委派模型
? ? ? 1.自己編寫的類加載器可以根據(jù)需求選擇是否遵守雙親委派模型。
? ? ? 2.舉例來說,Tomcat是一個Web服務器,它需要加載Web應用程序中的類。在這種情況下,Tomcat可能會使用單獨的類加載器來加載Webapp,而不是遵循雙親委派模型。
? ? ? 3.這樣做的好處是可以避免不同Web應用程序之間的類沖突,并且可以更好地控制每個Web應用程序的類加載過程。然而,如果一個自定義的類加載器不遵循雙親委派模型,那么它必須自行處理類的查找和加載,這可能會導致一些額外的復雜性和潛在的問題。因此,是否遵守雙親委派模型主要取決于具體的需求和設計決策。?
?以上就是JVM類加載機制的簡單介紹。