欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JVM虛擬機的類加載機制詳解

 更新時間:2023年12月19日 09:47:11   作者:初念初戀  
這篇文章主要介紹了JVM虛擬機的類加載機制詳解,類是在運行期間第一次使用時動態(tài)加載的,而不是一次性加載所有類,因為如果一次性加載,那么會占用很多的內(nèi)存,需要的朋友可以參考下

一、類的生命周期

類是在運行期間第一次使用時動態(tài)加載的,而不是一次性加載所有類。因為如果一次性加載,那么會占用很多的內(nèi)存。

11.png

包括以下 7 個階段:

  • 加載(Loading)
  • 驗證(Verification)
  • 準備(Preparation)
  • 解析(Resolution)
  • 初始化(Initialization)
  • 使用(Using)
  • 卸載(Unloading)

二、類的加載過程

包含了加載、驗證、準備、解析和初始化這 5 個階段。

加載

加載過程完成以下三件事:

  • 通過類的完全限定名稱獲取定義該類的二進制字節(jié)流。
  • 將該字節(jié)流表示的靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)換為方法區(qū)的運行時存儲結(jié)構(gòu)。
  • 在內(nèi)存中生成一個代表該類的 Class 對象,作為方法區(qū)中該類各種數(shù)據(jù)的訪問入口。

其中二進制字節(jié)流可以從以下方式中獲?。?/p>

  • 從 ZIP 包讀取,成為 JAR、EAR、WAR 格式的基礎(chǔ)。
  • 從網(wǎng)絡(luò)中獲取,最典型的應(yīng)用是 Applet。
  • 運行時計算生成,例如動態(tài)代理技術(shù),在 java.lang.reflect.Proxy 使用 ProxyGenerator.generateProxyClass 的代理類的二進制字節(jié)流。
  • 由其他文件生成,例如由 JSP 文件生成對應(yīng)的 Class 類。

驗證

JVM 會在該階段對二進制字節(jié)流進行校驗,只有符合 JVM 字節(jié)碼規(guī)范的才能被 JVM 正確執(zhí)行。該階段是保證 JVM 安全的重要屏障,下面是一些主要的檢查。

  • 確保二進制字節(jié)流格式符合預(yù)期(比如說是否以 cafe bene 開頭)。
  • 是否所有方法都遵守訪問控制關(guān)鍵字的限定。
  • 方法調(diào)用的參數(shù)個數(shù)和類型是否正確。
  • 確保變量在使用之前被正確初始化了。
  • 檢查變量是否被賦予恰當類型的值。

準備

JVM 會在該階段對類變量(也稱為靜態(tài)變量,static 關(guān)鍵字修飾的)分配內(nèi)存并初始化(對應(yīng)數(shù)據(jù)類型的默認初始值,如 0、0L、null、false 等)。

此時不會分配實例變量的內(nèi)存,因為實例變量是在實例化對象時一起創(chuàng)建在Java 堆中的。而且此時類變量是賦值為零值,即 int 類型的零值為 0,引用類型零值為 null,而不是代碼中顯示賦值的數(shù)值。

解析

該階段將常量池中的符號引用轉(zhuǎn)化為直接引用。

在 class 文件中常量池里面存放了字面量和符號引用,符號引用包括類和接口的全限定名以及字段和方法的名稱與描述符。

在 JVM 動態(tài)鏈接的時候需要根據(jù)這些符號引用來轉(zhuǎn)換為直接引用存放內(nèi)存使用。

初始化

該階段是類加載過程的最后一步。在準備階段,類變量已經(jīng)被賦過默認初始值,而在初始化階段,類變量將被賦值為代碼期望賦的值。換句話說,初始化階段是執(zhí)行類構(gòu)造器方法的過程。

三、類加載時機

  • new、getstatic、putstatic、invokestatic 這 4 個字節(jié)碼指令時對類進行初始化(即:實例化對象、讀寫靜態(tài)對象、調(diào)用靜態(tài)方法時,進行類的初始化);
  • 使用反射機制對類進行調(diào)用時,進行類的初始化;
  • 初始化一個類,其父類沒有初始化時,先初始化其父類;
  • 虛擬機啟動時,初始化一個執(zhí)行主類;
  • 使用 JDK1.7 的動態(tài)語言支持時,如果 MethodHandle 實例的解析結(jié)果為 REF_getstatic、REF_putstatic、REF_invokestatic 的方法句柄(即:讀寫靜態(tài)對象或者調(diào)用靜態(tài)方法),則初始化該句柄對應(yīng)類。

四、類加載器分類

講到類加載不得不講到類加載的順序和類加載器。

Java 中大概有四種類加載器,分別是:啟動類加載器(Bootstrap ClassLoader),擴展類加載器(Extension ClassLoader),系統(tǒng)類加載器(System ClassLoader),自定義類加載器(Custom ClassLoader),依次屬于繼承關(guān)系(注意這里的繼承不是 Java 類里面的 extends)

classloader2.jpg

  • 啟動類加載器(Bootstrap ClassLoader):主要負責加載存放在Java_Home/jre/lib下,或被-Xbootclasspath參數(shù)指定的路徑下的,并且能被虛擬機識別的類庫(如rt.jar,所有的java.*開頭的類均被Bootstrap ClassLoader加載),啟動類加載器是無法被Java程序直接引用的。
  • 擴展類加載器(Extension ClassLoader):主要負責加載器由sun.misc.Launcher$ExtClassLoader實現(xiàn),它負責加載Java_Home/jre/lib/ext目錄中,或者由java.ext.dirs系統(tǒng)變量指定的路徑中的所有類庫(如javax.*開頭的類),開發(fā)者可以直接使用擴展類加載器。
  • 系統(tǒng)類加載器(System ClassLoader):主要負責加載器由sun.misc.Launcher$AppClassLoader來實現(xiàn),它負責加載用戶類路徑(ClassPath)所指定的類,開發(fā)者可以直接使用該類加載器,如果應(yīng)用程序中沒有自定義過自己的類加載器,一般情況下這個就是程序中默認的類加載器。
  • 自定義類加載器(Custom ClassLoader:自己開發(fā)的類加載器。

五、雙親委派原則

類加載器在加載 class 文件的時候,遵從雙親委派原則,意思是加載依次由父加載器先執(zhí)行加載動作,只有當父加載器沒有加載到 class 文件時才由子類加載器進行加載。這種機制很好的保證了 Java API 的安全性,使得 JDK 的代碼不會被篡改。

六、Java字節(jié)碼文件中的JVM指令

1、創(chuàng)建一個 Java 源文件 Test02.java,并在 main 方法中完成簡單的邏輯操作,如下所示。

public class Test02 {
    public static void main(String[] args) {
        int i = 5;
        int j = 10;
        int k = i + j;
        System.out.println(k);
    }
}

2、在終端通過 javac 命令編譯 HelloWorld.java。

javac Test02.java

3、反編譯成我們能看懂的 JVM 指令,這里我們使用 javap -c 命令完成。

javap -c Test02.class

4、反編譯之后的 JVM 指令如下所示。

    Compiled from "Test02.java"
    public class org.example.jvm.Test02 {
     public org.example.jvm.Test02();
        Code:
           0: aload_0
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return
      public static void main(java.lang.String[]);
         Code:
           0: iconst_5
           1: istore_1
           2: bipush        10
           4: istore_2
           5: iload_1
           6: iload_2
           7: iadd
           8: istore_3
           9: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
          12: iload_3
          13: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
          16: return
    }

解釋一下上述的 JVM 指令:

第 1 行表示當前的字節(jié)碼文件編譯自 Test02.java。

第 3 行表示調(diào)用 Test02的無參構(gòu)造函數(shù)來實例化當前對象。

第 4 行到第 7 行表示無參構(gòu)造函數(shù)的執(zhí)行流程。

第 5 行表示把 this 壓入操作數(shù)棧中。

第 6 行表示調(diào)用 Test02父類 Object 的無參構(gòu)造,我們知道每個對象在實例化的時候都會默認先實例化其父類對象,并且默認調(diào)用父類的無參構(gòu)造。

第 7 行 return 表示構(gòu)造方法執(zhí)行完畢。

第 10 行到第 22 行表示 main 方法的執(zhí)行流程。

第 11 行表示將常量 5 壓入操作數(shù)棧。

第 12 行表示取出操作數(shù)棧棧頂元素,即 5,然后保存到局部變量表第 1 個位置,即變量 i。

第 13 行表示將常量 10 壓入操作數(shù)棧。

第 14 行表示取出操作數(shù)棧棧頂元素,即 10,然后保存到局部變量表第 2 個位置,即變量 j。

第 15 行表示將局部變量表第 1 個變量(i)壓入操作數(shù)棧。

第 16 行表示將局部變量表第 2 個變量(j)壓入操作數(shù)棧。

第 17 行表示取出操作數(shù)棧中的前兩個值相加,并將結(jié)果壓入操作數(shù)棧頂。

第 18 行表示取出操作數(shù)棧棧頂元素,保存到局部變量表第 3 個位置,即變量 k。

第 19 行表示讀取靜態(tài)實例 PrintStream。

第 20 行表示將局部變量表第 3 個變量(k)壓入操作數(shù)棧。

第 21 行表示調(diào)用 PrintStream 的 println 方法,將操作數(shù)棧頂元素(變量 k)輸出。

第 22 行 return 表示 main 方法執(zhí)行完畢。

到此這篇關(guān)于JVM虛擬機的類加載機制詳解的文章就介紹到這了,更多相關(guān)JVM類加載機制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 使用原生JDBC動態(tài)解析并獲取表格列名和數(shù)據(jù)的方法

    使用原生JDBC動態(tài)解析并獲取表格列名和數(shù)據(jù)的方法

    這篇文章主要介紹了使用原生JDBC動態(tài)解析并獲取表格列名和數(shù)據(jù),本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-08-08
  • SpringBoot?AOP統(tǒng)一處理Web請求日志的示例代碼

    SpringBoot?AOP統(tǒng)一處理Web請求日志的示例代碼

    springboot有很多方法處理日志,例如攔截器,aop切面,service中代碼記錄等,下面這篇文章主要給大家介紹了關(guān)于SpringBoot?AOP統(tǒng)一處理Web請求日志的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • MyBatis綁定錯誤提示BindingException:Invalid bound statement (not found)的解決方法

    MyBatis綁定錯誤提示BindingException:Invalid bound statement (not f

    這篇文章主要介紹了MyBatis綁定錯誤提示BindingException:Invalid bound statement (not found)的解決辦法,非常不錯,具有參考借鑒價值,需要的的朋友參考下吧
    2017-01-01
  • SpringBoot項目啟動錯誤:找不到或無法加載主類的三種解決方法

    SpringBoot項目啟動錯誤:找不到或無法加載主類的三種解決方法

    在開發(fā)SpringBoot應(yīng)用時,經(jīng)??赡軙龅揭粋€啟動錯誤:“錯誤:找不到或無法加載主類 com.example.controller.demo.DemoApplication”,本文將介紹三種解決這一問題的方法,需要的朋友可以參考下
    2024-10-10
  • 詳解java自定義類

    詳解java自定義類

    這篇文章主要介紹了java自定義類的概念以及用法,文中講解非常詳細,實例代碼幫助大家更好的理解,感興趣的朋友可以參考下
    2020-06-06
  • java如何獲取yml配置文件工具類

    java如何獲取yml配置文件工具類

    本文介紹了java獲取yml配置文件的工具類引入pom文件的方法,首先,創(chuàng)建一個與工具類同名的類,然后將工具類的代碼復(fù)制到新創(chuàng)建的類中,運行后輸出:0*/1***?完成操作,此方法簡單易行,適合初學(xué)者使用
    2024-10-10
  • spring中使用@Autowired注解無法注入的情況及解決

    spring中使用@Autowired注解無法注入的情況及解決

    這篇文章主要介紹了spring中使用@Autowired注解無法注入的情況及解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • JMeter自定義日志與日志分析的實現(xiàn)

    JMeter自定義日志與日志分析的實現(xiàn)

    JMeter與Java程序一樣,會記錄事件日志,本文就介紹一下JMeter自定義日志與日志分析的實現(xiàn),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • MyBatis多數(shù)據(jù)源的兩種配置方式

    MyBatis多數(shù)據(jù)源的兩種配置方式

    這篇文章主要給大家介紹了關(guān)于MyBatis多數(shù)據(jù)源的兩種配置方式,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-12-12
  • 在Java的Hibernate框架中對數(shù)據(jù)庫數(shù)據(jù)進行查詢操作

    在Java的Hibernate框架中對數(shù)據(jù)庫數(shù)據(jù)進行查詢操作

    這篇文章主要介紹了Java的Hibernate框架中對數(shù)據(jù)庫數(shù)據(jù)進行查詢操作的方法,Hibernate是Java的SSH三大web開發(fā)框架之一,需要的朋友可以參考下
    2015-12-12

最新評論