91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java類加載是什么意思

發布時間:2021-06-23 14:47:00 來源:億速云 閱讀:219 作者:chen 欄目:編程語言

本篇內容介紹了“Java類加載是什么意思”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

1 來源

  • 來源:《Java高并發編程詳解 多線程與架構設計》

2 類加載簡介

類加載的過程可以簡單分為三個階段:

  • 加載階段:主要負責查找并且加載類的二進制數據文件

  • 連接階段:可以細分為驗證、準備、解析三個階段,驗證就是確保類文件的正確性,準備就是為類的靜態變量分配內存,并且為其初始化默認值,解析就是把類中的符號引用轉換為直接引用

  • 初始化階段:為類的靜態變量賦予正確的初始值

3 主動使用與被動使用

JVM規范規定了每個類或接口在首次主動使用的時候都需要進行初始化,規定了以下六種主動使用類的場景:

  • 通過new關鍵字會導致類的初始化

  • 訪問類的靜態變量

  • 訪問類的靜態方法

  • 對某個類進行反射操作

  • 初始化子類會導致父類初始化

  • 啟動類(就是包含main()的類)也會初始化

除了以上六種情況外,其余的都叫被動使用,不會導致類的加載和初始化,比如引用類的靜態常量不會導致類的初始化。

4 類加載詳解

前面也說了類加載可以簡單分為三個階段:

  • 加載階段

  • 連接階段

  • 初始化階段

下面先來看一下加載階段。

4.1 加載階段

加載階段就是將class文件中的二進制數據讀取到內存之中,然后將該字節流代表的靜態存儲結構轉換為方法區中運行時數據結構,并且在堆中生成一個該類的java.lang.Class對象,作為訪問方法區數據結構的入口。

類加載的最終產物就是堆內存中的class對象,JVM規范中指出類加載是通過一個全限定名去獲取二進制數據流,來源包括:

  • class文件:這是最常見的格式,就是加載javac編譯后的字節碼文件

  • 運行時動態生成:比如ASM可以動態生成,或者可以通過動態代理java.lang.Proxy生成等

  • 通過網絡獲取:比如RMI

  • 讀取壓縮文件:比如JARWAR

  • 從數據庫讀取:比如讀取MySQL中的BLOB字段類型的數據

  • 運行時生成class文件并且動態加載:比如ThriftAvro等序列化框架,將某個schema生成若干個class文件并進行加載

類加載階段結束后,JVM會將這些二進制字節流按照JVM定義的格式存放在方法區中,形成特定的數據結構后再在堆內存中實例化一個java.lang.Class對象。

4.2 連接階段

該階段可以分為三個小階段:

  • 驗證

  • 準備

  • 解析

需要注意的是這三個小階段其實不是順序進行的,而是交叉著進行的,也就是解析的時候其實也會有驗證的過程。

4.2.1 驗證

驗證是為了確保字節流所包含的內容符合JVM規范,并且不會出現危害JVM自身安全的代碼,當字節流信息不符合要求的時候,會拋出VerifyError這樣的異常或其子異常,驗證的信息包括:

  • 文件格式

  • 元數據

  • 字節碼

  • 符號引用

4.2.1.1 驗證文件格式

包括:

  • 魔數(0xCAFEBABE

  • 主次版本號

  • 是否存在殘缺或附加信息

  • 常量池常量類型是否支持

  • 常量池引用是否指向不存在常量或不支持類型常量

  • 其他

4.2.1.2 驗證元數據

元數據驗證其實是進行語義分析的過程,語義分析是為了確保字節流符合JVM規范要求,包括:

  • 檢查某個類是否存在父類,是否繼承某個接口,這些父類或接口是否合法,或是否存在

  • 檢查是否繼承了final的類

  • 檢查抽象類,檢查是否實現了父類的抽象方法或接口方法

  • 檢查重載,比如相同的方法名稱、相同的參數但是返回類型不同,這是不允許的

4.2.1.3 驗證字節碼

字節碼驗證主要是驗證程序的控制流程,包括:

  • 保證當前線程在程序計數器中的指令不會跳轉到不合法的字節碼指令中去

  • 保證類型的轉換是合法的

  • 保證任意時刻虛擬機棧中的操作棧類型與指令代碼都能正確被執行

  • 其他驗證

4.2.1.4 驗證符號引用

驗證符號引用轉換為直接引用的合法性,保證解析動作的順利執行,包括:

  • 通過符號引用描述的字符串全限定名稱是否能夠順利找到相關的類

  • 符號引用中的類、字段、方法是否對當前類可見

  • 其他

4.2.2 準備

經過驗證后,就開始了準備階段,這階段比較簡單,就是對對象的靜態變量分配內存并且設置初始值,類變量的內存會被分配到方法區中。設置初始值就是為相應的類變量給定一個相關類型在沒有被設置時的默認值,比如Int的初始值為0,引用的初始值為null

4.2.3 解析

解析就是在常量池中尋找類、字段、接口和方法的符號引用,并且將這些符號引用替換成直接引用的過程。解析主要針對類接口、字段、類方法和接口方法進行的,包括:

  • 類接口解析

  • 字段解析

  • 類方法解析

  • 接口方法解析

4.3 初始化階段

初始化階段主要就是執行<clinit>方法的過程,該方法是編譯階段生成的,也就是說包含在字節碼文件中,該方法包含了所有類變量的賦值動作和靜態語句塊的執行代碼。另一方面,<clinit>與構造方法不同,不需要顯式調用父類構造器,虛擬機會保證父類的<clinit>方法最先執行。

還需要注意的是<clinit>只能被虛擬機執行,虛擬機還會保證多線程下的安全性,因此,如果在靜態代碼塊中如果包含了加載其他類的操作可能會引起死鎖,例子可以看這里。

5 類加載器

5.1 JVM中的三類核心類加載器

JVM中有三類核心類加載器,分別是:

  • 啟動類加載器:啟動類加載器是最頂層的類加載器,沒有父加載器,由C++編寫,負責JVM核心類庫的加載,比如加載整個java.lang包中的類

  • 擴展類加載器:擴展類加載器的父加載器是啟動類加載器,主要加載jre/lib/ext子目錄下的類庫,純Java實現,是URLClassLoader的子類

  • 應用類加載器:也叫系統類加載器,負責加載classpath下的類庫,應用類加載器的父加載器為擴展類加載器,同時它也是自定義類加載器的默認父加載器

5.2 雙親委派機制

一個類加載器加載一個類的時候,并不會嘗試直接加載該類,而是先交給父加載器嘗試加載,一直到頂層的父加載器(啟動類加載器),如果父加載器加載失敗,則會自己嘗試加載,圖示如下:

Java類加載是什么意思

6 線程上下文類加載器

JDK中提供了很多SPIService Provider Interface),比如JDBC等,JDBC只規定了這些接口之間的邏輯關系,但不提供具體的實現,換句話說,JDBC完全透明了應用程序和第三方廠商數據庫驅動的具體實現,應用程序只需要面向接口編程即可。但問題是:

  • java.lang.sql中的所有接口都是由JDK提供的,加載這些接口的類加載器是啟動類加載器

  • 第三方廠商的類庫驅動由系統類加載器加載

由于雙親委派機制,ConnectionsStatement等都是由啟動類加載器加載,而第三方JDBC驅動包中的實現不會被加載。解決這個問題的關鍵,就是使用了線程上下文類加載器打破了雙親委派機制。

比如MySQL驅動的加載過程,就是通過線程上下文類加載器加載的,

private static Connection getConnection(String url, Properties info, Class<?> caller) throws SQLException {
        //...
        if (callerCL == null || callerCL == ClassLoader.getPlatformClassLoader()) {
            callerCL = Thread.currentThread().getContextClassLoader();
        }
		while(true) {
			//...
			if (isDriverAllowed(aDriver.driver, callerCL)) {
			}
		}
		//...
}
private static boolean isDriverAllowed(Driver driver, ClassLoader classLoader) {
	//...
    try {
        aClass = Class.forName(driver.getClass().getName(), true, classLoader);
    } catch (Exception var5) {
        result = false;
    }
    //...
    return result;
}

通過線程上下文類加載器,就變成了啟動類加載器去委托子類加載器去加載實現的方式,也就是JDK自己親自打破了雙親委派機制這種方式,這種加載方式幾乎涉及所有的SPI加載,包括JAXBJCEJBI等。

“Java類加載是什么意思”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

开阳县| 婺源县| 都匀市| 永吉县| 宁国市| 宜宾县| 渑池县| 高青县| 称多县| 遂溪县| 乳源| 噶尔县| 资源县| 得荣县| 会宁县| 邻水| 崇仁县| 湘西| 新郑市| 浪卡子县| 绍兴县| 福建省| 榆中县| 井研县| 昭苏县| 肃宁县| 深泽县| 鸡东县| 抚远县| 莒南县| 枝江市| 什邡市| 永顺县| 响水县| 靖安县| 克什克腾旗| 高阳县| 肃南| 彩票| 罗城| 河池市|