亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

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

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

JVM的類加載器和雙親委派模式實例分析

發布時間:2022-03-14 09:09:46 來源:億速云 閱讀:150 作者:iii 欄目:開發技術

這篇文章主要講解了“JVM的類加載器和雙親委派模式實例分析”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“JVM的類加載器和雙親委派模式實例分析”吧!

    類加載器

    Java虛擬機設計團隊有意把類加載階段中的“通過一個類的全限定名來獲取描述該類的二進制字節流”這個動作放到Java虛擬機外部去實現,以便讓應用程序自己決定如何去獲取所需的類。實現這個動作的代碼被稱為“類加載器”(ClassLoader)。

    對于任意一個類,都必須由加載它的類加載器和這個類本身一起共同確立其在Java虛擬機中的唯一性,每一個類加載器,都擁有一個獨立的類名稱空間。這句話可以表達得更通俗一些:比較兩個類是否“相等”,只有在這兩個類是由同一個類加載器加載的前提下才有意義,否則,即使這兩個類來源于同一個Class文件,被同一個Java虛擬機加載,只要加載它們的類加載器不同,那這兩個類就必定不相等

    名稱加載的類說明
    Bootstrap ClassLoader(啟動類加載器)JAVA_HOME/jre/lib無法直接訪問
    Extension ClassLoader(拓展類加載器)JAVA_HOME/jre/lib/ext上級為Bootstrap,顯示為null
    Application ClassLoader(應用程序類加載器)classpath上級為Extension
    自定義類加載器自定義上級為Application

    1、啟動類加載器

    可通過在控制臺輸入指令,使得類被啟動類加器加載,它是用C++寫的,看不到源碼;其他類加載器是用Java寫的,說白了就是一些Java類,比如擴展類加載器、應用類加載器。

    //查詢所有被啟動類加載器加載的類
    URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs();
    for (URL url : urls) {
        System.out.println(url);
    }
    //查詢到的結果
    file:/C:/Program%20Files/Java/jre1.8.0_131/lib/resources.jar
    file:/C:/Program%20Files/Java/jre1.8.0_131/lib/rt.jar
    file:/C:/Program%20Files/Java/jre1.8.0_131/lib/sunrsasign.jar
    file:/C:/Program%20Files/Java/jre1.8.0_131/lib/jsse.jar
    file:/C:/Program%20Files/Java/jre1.8.0_131/lib/jce.jar
    file:/C:/Program%20Files/Java/jre1.8.0_131/lib/charsets.jar
    file:/C:/Program%20Files/Java/jre1.8.0_131/lib/jfr.jar
    file:/C:/Program%20Files/Java/jre1.8.0_131/classes

    由上可以看出啟動類加載的都是jre和jre/lib目錄下的核心庫,具體路徑要看你的jre安裝在哪里

    2、拓展類加載器

    如果classpath和JAVA_HOME/jre/lib/ext 下有同名類,加載時會使用拓展類加載器加載。當應用程序類加載器發現拓展類加載器已將該同名類加載過了,則不會再次加載

    URL[] urls = ((URLClassLoader) ClassLoader.getSystemClassLoader().getParent()).getURLs();
    for (URL url : urls) {
        System.out.println(url);
    }
    file:/C:/Program%20Files/Java/jre1.8.0_131/lib/ext/access-bridge-64.jar
    file:/C:/Program%20Files/Java/jre1.8.0_131/lib/ext/cldrdata.jar
    file:/C:/Program%20Files/Java/jre1.8.0_131/lib/ext/dnsns.jar
    file:/C:/Program%20Files/Java/jre1.8.0_131/lib/ext/dns_sd.jar
    file:/C:/Program%20Files/Java/jre1.8.0_131/lib/ext/jaccess.jar
    file:/C:/Program%20Files/Java/jre1.8.0_131/lib/ext/jfxrt.jar
    file:/C:/Program%20Files/Java/jre1.8.0_131/lib/ext/localedata.jar
    file:/C:/Program%20Files/Java/jre1.8.0_131/lib/ext/nashorn.jar
    file:/C:/Program%20Files/Java/jre1.8.0_131/lib/ext/sunec.jar
    file:/C:/Program%20Files/Java/jre1.8.0_131/lib/ext/sunjce_provider.jar
    file:/C:/Program%20Files/Java/jre1.8.0_131/lib/ext/sunmscapi.jar
    file:/C:/Program%20Files/Java/jre1.8.0_131/lib/ext/sunpkcs11.jar
    file:/C:/Program%20Files/Java/jre1.8.0_131/lib/ext/zipfs.jar

    這些類庫具體是什么不重要,只需要知道不同的類庫可能是被不同的類加載器加載的。

    3、應用程序類加載器

    URL[] urls = ((URLClassLoader) ClassLoader.getSystemClassLoader()).getURLs();
    for (URL url : urls) {
        System.out.println(url);
    }
    file:/{項目工程目錄}/bin/

    這是當前java工程的bin目錄,也就是我們自己的Java代碼編譯成的class文件所在。

    4、雙親委派模式

    雙親委派模式,調用類加載器ClassLoader 的 loadClass 方法時,查找類的規則。

    loadClass源碼

    protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // 首先查找該類是否已經被該類加載器加載過了
            Class<?> c = findLoadedClass(name);
            //如果沒有被加載過
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    //看是否被它的上級加載器加載過了 Extension的上級是Bootstarp,但它顯示為null
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        //看是否被啟動類加載器加載過
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                    //捕獲異常,但不做任何處理
                }
                if (c == null) {
                    //如果還是沒有找到,先讓拓展類加載器調用findClass方法去找到該類,如果還是沒找到,就拋出異常
                    //然后讓應用類加載器去找classpath下找該類
                    long t1 = System.nanoTime();
                    c = findClass(name);
                    // 記錄時間
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

    有一個描述類加載器加載類過程的術語:雙親委派模型。然而這是一個很有誤導性的術語,它應該叫做單親委派模型(Parent-Delegation Model)。但是沒有辦法,大家都已經這樣叫了。所謂雙親委派,這個親就是指ClassLoader里的全局變量parent,也就是父加載器。

    雙親委派的具體過程如下:

    • 當一個類加載器接收到類加載任務時,先查緩存里有沒有,如果沒有,將任務委托給它的父加載器去執行。

    • 父加載器也做同樣的事情,一層一層往上委托,直到最頂層的啟動類加載器為止。

    • 如果啟動類加載器沒有找到所需加載的類,便將此加載任務退回給下一級類加載器去執行,而下一級的類加載器也做同樣的事情。

    • 如果最底層類加載器仍然沒有找到所需要的class文件,則拋出異常。

    • 所以是一條線傳上再傳下,并沒有什么“雙親”。

    JVM的類加載器和雙親委派模式實例分析

    為什么要雙親委派?

    :確保類的全局唯一性。

    如果你自己寫的一個類與核心類庫中的類重名,會發現這個類可以被正常編譯,但永遠無法被加載運行。因為你寫的這個類不會被應用類加載器加載,而是被委托到頂層,被啟動類加載器在核心類庫中找到了。如果沒有雙親委托機制來確保類的全局唯一性,誰都可以編寫一個java.lang.Object類放在classpath下,那應用程序就亂套了。

    從安全的角度講,通過雙親委托機制,Java虛擬機總是先從最可信的Java核心API查找類型,可以防止不可信的類假扮被信任的類對系統造成危害。

    5、自定義類加載器

    如果我們自己去實現一個類加載器,基本上就是繼承ClassLoader之后重寫findClass方法,且在此方法的最后調包defineClass。

    5.1、使用場景
    • 想加載非 classpath 隨意路徑中的類文件

    • 通過接口來使用實現,希望解耦時,常用在框架設計

    • 這些類希望予以隔離,不同應用的同名類都可以加載,不沖突,常見于 tomcat 容器

    5.2、步驟
    • 繼承ClassLoader父類

    • 要遵從雙親委派機制,重寫 ?ndClass 方法

      • 不是重寫loadClass方法,否則不會走雙親委派機制

    • 讀取類文件的字節碼

    • 調用父類的 de?neClass 方法來加載類

    • 使用者調用該類加載器的 loadClass 方法

    protected Class<?> findClass(final String name) throws ClassNotFoundException {
        // 1、安全檢查
        // 2、根據絕對路徑把硬盤上class文件讀入內存
        byte[] raw = getBytes(name); 
        // 3、將二進制數據轉換成class對象
        return defineClass(raw);
    }

    感謝各位的閱讀,以上就是“JVM的類加載器和雙親委派模式實例分析”的內容了,經過本文的學習后,相信大家對JVM的類加載器和雙親委派模式實例分析這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

    向AI問一下細節

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

    jvm
    AI

    宜兰市| 通江县| 仙桃市| 新密市| 肥乡县| 崇义县| 广元市| 泗水县| 太湖县| 隆昌县| 泰顺县| 洛隆县| 汕尾市| 象山县| 长武县| 林口县| 格尔木市| 昌邑市| 靖安县| 拜城县| 临沭县| 广州市| 台江县| 庆阳市| 兴安盟| 老河口市| 桐梓县| 淳化县| 万山特区| 泾阳县| 威信县| 丘北县| 郓城县| 洪泽县| 榆社县| 屏边| 黄大仙区| 安塞县| 宜阳县| 巨鹿县| 会理县|