最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

jvm虛擬機類加載機制詳解

 更新時間:2022年04月19日 15:00:11   作者:我的Coder小屋  
本文主要介紹了 jvm虛擬機類加載機制詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

1 概述

? Java虛擬機把描述類的數據從Class文件加載到內存, 并對數據進行校驗、轉化解析和初始化,最終形成可以被虛擬機直接使用的Java類型,這個過程稱為虛擬機的類加載機制。在Java語言中,類型的加載、連接和初始化都是在程序運行期間完成的。

2 類的加載時機

? 一個類型從被加載到虛擬機內存中開始,到卸載出內存為止,它的整個生命周期將會經歷加載、驗證、準備、解析、初始化、使用和卸載七個階段,其中驗證、準備和解析三個部分統稱為連接。發(fā)生順序如下:

在這里插入圖片描述

? 《Java虛擬機規(guī)范》嚴格規(guī)定有且只有六種情況必須立即對類進行“初始化”(加載、驗證和準備自然需要在此之前開始):

  • 遇到new、getstatic、putstatic或invokestatic這四條字節(jié)碼指令時,如果類型沒有進行初始化,則需要先觸發(fā)其初始化階段。能夠生成這四條指令的典型Java代碼場景有:
    • 使用new關鍵字實例化對象的時候
    • 讀取或設置一個類型的靜態(tài)字段的時候
    • 調用一個類型的靜態(tài)方法的時候
  • 使用java.lang.reflect包的方法對類型進行反射調用的時候,如果還沒被初始化,則需要先觸發(fā)其初始化。
  • 當初始化類的時候,如果發(fā)現其父類還沒進行過初始化,則需要先觸發(fā)其父類的初始化。
  • 當虛擬機啟動時,用戶需要指定一個要執(zhí)行的主類。虛擬機會先初始化這個主類。
  • jdk1.7新加入的動態(tài)語言支持時。
  • 當一個接口中定義了jdk8新加入的默認方法時。

? 這六種場景的行為稱為對一個類型進行主動引用。除此之外,所有引用類型的方式都不會觸發(fā)初始化,稱為被動引用。下面舉出被動引用的例子

示例1:通過子類引用父類的靜態(tài)字段,不會導致子類初始化

public class NotInitialization {
    public static void main(String[] args) {
        System.out.println(SubClass.value);  // 只會輸出“SuperClass init”,而不會輸出“subclass init”
        SuperClass[] superClasses = new SuperClass[10];  // 不會輸出“SuperClass init”
    }
}

class SuperClass {
    static {
        System.out.println("SuperClass init");
    }
    public static int value = 123;
}

class SubClass extends SuperClass {
    static {
        System.out.println("SubClass init!");
    }
}

示例2:常量在編譯階段會存入調用類的常量池中,本質上沒有直接引用到定義常量的類,因此不會觸發(fā)定義常量的初始化

public class NotInitialization {
    public static void main(String[] args) {
        System.out.println(ConstClass.HELLOWORLD);  // 不會輸出“ConstClass init!”,因為常量直接存儲到常量池中。
    }
}
class ConstClass {
    static {
        System.out.println("ConstClass init!");
    }

    public static final String HELLOWORLD = "hello world";
}

class Test {
    static {
        i = 0;
    }
    static int i = 1;
}

3 類的加載過程

3.1 加載

? 在加載階段,虛擬機需要完成以下三件事情:

通過一個類的全限定名來獲取定義此類的二進制字節(jié)流。將這個字節(jié)流所代表的靜態(tài)存儲結構轉化為方法區(qū)的運行時數據結構。在內存中生成一個代表這個類的java.lang.Class對象,作為方法區(qū)這個類的的各種數據的訪問入口。

3.2 驗證

? 驗證是連接階段的第一步,這一階段的目的是確保Class文件的字節(jié)流中包含的信息符合《Java虛擬機規(guī)范》的約束要求,保證這些信息不會危害虛擬機自身。

3.3 準備

? 準備階段是正式為類中定義的變量(即靜態(tài)變量,被static修飾的變量)分配內存并設置類變量初始值的階段。

3.4 解析

? 解析階段是將常量池內的符號引用替換為直接引用的過程。

3.5 初始化

? 初始化是類加載過程的最后一個階段,直到初始化階段,Java虛擬機才真正開始執(zhí)行類中編寫的Java程序代碼,將主導權移交給應用程序。初始化階段就是執(zhí)行類構造器的()方法的過程。

  • ()方法與類的構造函數不同,它不需要顯示地調用父類構造器,Java虛擬機會保證在子類的()方法執(zhí)行前,父類的()方法已經執(zhí)行完畢。因此在Java虛擬機中第一個被執(zhí)行的()方法肯定是Object。
  • 由于父類的()方法先執(zhí)行,也就意味著父類中定義的靜態(tài)語句塊要優(yōu)先于子類的變量賦值操作,如下代碼:字段值將會是2而不是1。
public static void main(String[] args) {
    System.out.println(Sub.B);
}

static class Parent {
    public static int A = 1;
    static {
        A = 2;
    }
}

static class Sub extends Parent {
    public static int B = A;
}

4 類加載器

? 類加載器用于實現類的加載動作,JVM中內置了三個重要的ClassLoader,除了BootstrapClassLoader其他類加載器均由Java實現且全部繼承自java.lang.ClassLoader:

  • BootstrapClassLoader(啟動類加載器):最頂層的加載類,負責加載%JAVA_HOME%/lib目錄下的jar包和類或者被-X:bootclasspathc參數指定的路徑下的所有類。
  • Extension Class Loader(擴展類加載器):主要負責加載<JAVA_HOME>\lib\ext目錄中的所有類庫。
  • AppClassLoader(應用程序類加載器):面向我們用戶的加載器,負責加載當前應用的classpath中的所有jar包和類。

4.1 雙親委派模型

在這里插入圖片描述

? 如上圖:雙親委派模型的工作流程是如果一個類加載器收到了類加載的請求,它首先不會自己去嘗試加載這個類,而是把這個請求委派給父類加載器去完成,每一個層次的類加載器都是如此,因此所有的加載請求最終都應該傳送到最頂層的啟動類加載器中,只有當父加載器反饋自己無法完成這個加載請求時,子加載器才會嘗試自己去完成加載。

好處

Java中的類隨著它的類加載器一起具備了一種帶有優(yōu)先級的層次關系。

實現

private final ClassLoader parent; 
protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // 首先,檢查請求的類是否已經被加載過
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {//父加載器不為空,調用父加載器loadClass()方法處理
                        c = parent.loadClass(name, false);
                    } else {//父加載器為空,使用啟動類加載器 BootstrapClassLoader 加載
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                   //拋出異常說明父類加載器無法完成加載請求
                }
                
                if (c == null) {
                    long t1 = System.nanoTime();
                    //自己嘗試加載
                    c = findClass(name);

                    // this is the defining class loader; record the stats
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

4.2 破壞雙親委派模型

? 雙親委派模型主要出現過3次較大規(guī)模的“被破壞”的情況。具體想了解的詳看《深入理解Java虛擬機》。

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

相關文章

  • Spring?Boot項目傳參校驗的最佳實踐指南

    Spring?Boot項目傳參校驗的最佳實踐指南

    有參數傳遞的地方都少不了參數校驗,在web開發(fā)中前端的參數校驗是為了用戶體驗,后端的參數校驗是為了安全,下面這篇文章主要給大家介紹了關于Spring?Boot項目傳參校驗的最佳實踐,需要的朋友可以參考下
    2022-04-04
  • java切分字符串的2種方法實例

    java切分字符串的2種方法實例

    在我們日常工作中經常遇到截取字符串的需求,下面這篇文章主要給大家介紹了關于java切分字符串的2種方法,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-06-06
  • JavaFX Application應用實例

    JavaFX Application應用實例

    下面小編就為大家?guī)硪黄狫avaFX Application應用實例。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-10-10
  • 在SpringBoot中配置Thymeleaf的模板路徑方式

    在SpringBoot中配置Thymeleaf的模板路徑方式

    這篇文章主要介紹了在SpringBoot中配置Thymeleaf的模板路徑方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • JAVA中的FileWriter流解析

    JAVA中的FileWriter流解析

    這篇文章主要介紹了JAVA中的FileWriter流解析,FileWriter類提供了多種寫入字符的方法,包括寫入單個字符、寫入字符數組和寫入字符串等,它還提供了一些其他的方法,如刷新緩沖區(qū)、關閉文件等,需要的朋友可以參考下
    2023-10-10
  • Java中security與shiro的區(qū)別詳解

    Java中security與shiro的區(qū)別詳解

    這篇文章主要介紹了Java中security與shiro的區(qū)別詳解,Spring?Security在架構上將認證與授權分離,并提供了擴展點,它是一個輕量級的安全框架,它確?;赟pring的應用程序提供身份驗證和授權支持,需要的朋友可以參考下
    2023-08-08
  • SpringBoot微服務注冊分布式Consul的詳細過程

    SpringBoot微服務注冊分布式Consul的詳細過程

    這篇文章主要介紹了SpringBoot(微服務)注冊分布式Consul,Spring Boot應用可以通過向Consul注冊自身來實現服務發(fā)現和治理,使得其他服務可以在Consul中發(fā)現并調用它,需要的朋友可以參考下
    2023-04-04
  • 詳解Spring中的Transactional屬性

    詳解Spring中的Transactional屬性

    今天我在寫代碼的時候,看到了一個注解@Transactional(rollbackFor = Exception.class),今天就和大家分享一下,這個注解的用法,,需要的朋友可以參考下
    2021-05-05
  • 解決Maven中的依賴導包問題(組合技巧)

    解決Maven中的依賴導包問題(組合技巧)

    自從我開始接觸了以spring為框架的項目學習后,這個maven導包老是出現問題,每次在這個上面花費好多時間,于是乎打算寫一個秘籍出來,這篇文章主要介紹了解決Maven中的依賴導包問題,需要的朋友可以參考下
    2023-11-11
  • Java并發(fā)編程之同步容器與并發(fā)容器詳解

    Java并發(fā)編程之同步容器與并發(fā)容器詳解

    今天給大家?guī)淼奈恼率荍ava并發(fā)編程的相關知識,文中對java同步容器與并發(fā)容器做了非常詳細的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06

最新評論

京山县| 东至县| 河北省| 八宿县| 安吉县| 永善县| 昔阳县| 光泽县| 巴青县| 东城区| 常熟市| 桃江县| 阳江市| 广州市| 封丘县| 广丰县| 绥阳县| 惠东县| 灵川县| 明溪县| 永新县| 淄博市| 漠河县| 博乐市| 拜城县| 蒙山县| 和龙市| 遂平县| 灵寿县| 巴中市| 松江区| 哈密市| 米易县| 阜新市| 策勒县| 江西省| 盐津县| 永康市| 宁武县| 新丰县| 伊宁县|