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

Java中的ClassLoader雙親委派機(jī)制詳解

 更新時(shí)間:2025年05月16日 17:25:04   作者:二六八  
這篇文章主要介紹了Java中的ClassLoader雙親委派機(jī)制,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

Java ClassLoader雙親委派機(jī)制

什么是雙親委派模型

“類加載體系”及ClassLoader雙親委派機(jī)制。java程序中的 .java文件編譯完會生成 .class文件,而 .class文件就是通過被稱為類加載器的ClassLoader加載的,而ClassLoder在加載過程中會使用“雙親委派機(jī)制”來加載 .class文件。

  1. BootStrapClassLoader:啟動類加載器,該ClassLoader是jvm在啟動時(shí)創(chuàng)建的,用于加載 $JAVA_HOME/jre/lib下面的類庫(或者通過參數(shù)-Xbootclasspath指定)。由于引導(dǎo)類加載器涉及到虛擬機(jī)本地實(shí)現(xiàn)細(xì)節(jié),開發(fā)者無法直接獲取到啟動類加載器的引用,所以不能直接通過引用進(jìn)行操作(由c++編寫)。
  2. ExtClassLoader:擴(kuò)展類加載器,該ClassLoader是在sun.misc.Launcher里作為一個(gè)內(nèi)部類ExtClassLoader定義的(即 sun.misc.Launcher$ExtClassLoader),ExtClassLoader會加載 $JAVA_HOME/jre/lib/ext下的類庫(或者通過參數(shù)-Djava.ext.dirs指定)。
  3. AppClassLoader:應(yīng)用程序類加載器,該ClassLoader同樣是在sun.misc.Launcher里作為一個(gè)內(nèi)部類AppClassLoader定義的(即 sun.misc.Launcher$AppClassLoader),AppClassLoader會加載java環(huán)境變量CLASSPATH所指定的路徑下的類庫,而CLASSPATH所指定的路徑可以通過System.getProperty(“java.class.path”)獲??;當(dāng)然,該變量也可以覆蓋,可以使用參數(shù)-cp,例如:java -cp 路徑 (可以指定要執(zhí)行的class目錄)。
  4. CustomClassLoader:自定義類加載器,該ClassLoader是指我們自定義的ClassLoader,比如tomcat的StandardClassLoader屬于這一類;當(dāng)然,大部分情況下使用AppClassLoader就足夠了。

ClassLoader的loadClass(String name, boolean resolve)源碼:

protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        // First, check if the class has already been loaded
        Class c = findLoadedClass(name);
        if (c == null) {
            try {
                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) {
                // If still not found, then invoke findClass in order
                // to find the class.
                c = findClass(name);
            }
        }
        if (resolve) {
            resolveClass(c);
        }
        return c;
    }

代碼很明朗:

首先找緩存(findLoadedClass),沒有的話就判斷有沒有parent,有的話就用parent來遞歸的loadClass,然而ExtClassLoader并沒有設(shè)置parent,則會通過findBootstrapClassOrNull來加載class,而findBootstrapClassOrNull則會通過JNI方法

private native Class findBootstrapClass(String name) 

來使用BootStrapClassLoader來加載class。

然后如果parent未找到class,則會調(diào)用findClass來加載class,findClass是一個(gè)protected的空方法,可以覆蓋它以便自定義class加載過程。

另外,雖然ClassLoader加載類是使用loadClass方法,但是鼓勵(lì)用 ClassLoader 的子類重寫 findClass(String),而不是重寫loadClass,這樣就不會覆蓋了類加載默認(rèn)的雙親委派機(jī)制。

雙親委派機(jī)制為什么安全

舉個(gè)例子,ClassLoader加載的class文件來源很多,比如編譯器編譯生成的class、或者網(wǎng)絡(luò)下載的字節(jié)碼。而一些來源的class文件是不可靠的,比如我可以自定義一個(gè)java.lang.Integer類來覆蓋jdk中默認(rèn)的Integer類,

例如下面這樣:

package java.lang;

public class Integer {
    public Integer(int value) {
        System.exit(0);
    }
}

初始化這個(gè)Integer的構(gòu)造器是會退出JVM,破壞應(yīng)用程序的正常進(jìn)行,如果使用雙親委派機(jī)制的話該Integer類永遠(yuǎn)不會被調(diào)用,因?yàn)槲蠦ootStrapClassLoader加載后會加載JDK中的Integer類而不會加載自定義的這個(gè),可以看下下面這測試個(gè)用例:

public static void main(String... args) {
        Integer i = new Integer(1);
        System.err.println(i);
    }

執(zhí)行時(shí)JVM并未在new Integer(1)時(shí)退出,說明未使用自定義的Integer,于是就保證了安全性。

為什么需要雙親委派模型

為什么需要雙親委派模型呢?假設(shè)沒有雙親委派模型,試想一個(gè)場景:

黑客自定義一個(gè)java.lang.String類,該String類具有系統(tǒng)的String類一樣的功能,只是在某個(gè)函數(shù)稍作修改。比如equals函數(shù),這個(gè)函數(shù)經(jīng)常使用,如果在這這個(gè)函數(shù)中,黑客加入一些“病毒代碼”。并且通過自定義類加載器加入到JVM中。此時(shí),如果沒有雙親委派模型,那么JVM就可能誤以為黑客自定義的java.lang.String類是系統(tǒng)的String類,導(dǎo)致“病毒代碼”被執(zhí)行。

而有了雙親委派模型,黑客自定義的java.lang.String類永遠(yuǎn)都不會被加載進(jìn)內(nèi)存。因?yàn)槭紫仁亲铐敹说念惣虞d器加載系統(tǒng)的java.lang.String類,最終自定義的類加載器無法加載java.lang.String類。

或許你會想,我在自定義的類加載器里面強(qiáng)制加載自定義的java.lang.String類,不去通過調(diào)用父加載器不就好了嗎?確實(shí),這樣是可行。但是,在JVM中,判斷一個(gè)對象是否是某個(gè)類型時(shí),如果該對象的實(shí)際類型與待比較的類型的類加載器不同,那么會返回false。

舉個(gè)簡單例子:

  • ClassLoader1、ClassLoader2都加載java.lang.String類,對應(yīng)Class1、Class2對象。
  • 那么Class1對象不屬于ClassLoad2對象加載的java.lang.String類型。

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 淺談java中對集合對象list的幾種循環(huán)訪問

    淺談java中對集合對象list的幾種循環(huán)訪問

    下面小編就為大家?guī)硪黄猨ava中對集合對象list的幾種循環(huán)訪問詳解。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-07-07
  • 一文帶你學(xué)習(xí)Java中的線程

    一文帶你學(xué)習(xí)Java中的線程

    線程是系統(tǒng)調(diào)度的最小單元,一個(gè)進(jìn)程可以包含多個(gè)線程,線程是負(fù)責(zé)執(zhí)行二進(jìn)制指令的。本文將詳細(xì)給大家介紹一下Java中的線程,,需要的朋友可以參考下
    2023-05-05
  • 詳解springboot的多種配置方式

    詳解springboot的多種配置方式

    這篇文章主要介紹了springboot的多種配置方式,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-10-10
  • windows下 jdk1.7安裝教程圖解

    windows下 jdk1.7安裝教程圖解

    java編程的初學(xué)者在開始編碼前都會遇到一個(gè)難題,那就是jdk1.7環(huán)境變量配置怎么操作,怎么安裝,針對這個(gè)難題,小編特地為大家整理相關(guān)教程,不了解的朋友可以前往查看使用
    2018-05-05
  • java集合類HashMap源碼解析

    java集合類HashMap源碼解析

    這篇文章主要介紹了Java集合之HashMap用法,結(jié)合實(shí)例形式分析了java map集合中HashMap定義、遍歷等相關(guān)操作技巧,需要的朋友可以參考下
    2021-06-06
  • 詳解RabbitMQ延遲隊(duì)列的基本使用和優(yōu)化

    詳解RabbitMQ延遲隊(duì)列的基本使用和優(yōu)化

    這篇文章主要介紹了詳解RabbitMQ延遲隊(duì)列的基本使用和優(yōu)化,延遲隊(duì)列中的元素都是帶有時(shí)間屬性的。延遲隊(duì)列就是用來存放需要在指定時(shí)間被處理的元素的隊(duì)列,需要的朋友可以參考下
    2023-05-05
  • springcloud如何配置文件加載順序

    springcloud如何配置文件加載順序

    這篇文章主要介紹了springcloud如何配置文件加載順序問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • Spring Boot 靜態(tài)資源處理方式

    Spring Boot 靜態(tài)資源處理方式

    這篇文章主要介紹了Spring Boot 靜態(tài)資源處理方式,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-09-09
  • Intellij Idea新建SpringBoot項(xiàng)目方式

    Intellij Idea新建SpringBoot項(xiàng)目方式

    這篇文章主要介紹了Intellij Idea新建SpringBoot項(xiàng)目方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-09-09
  • IntelliJ IDEA快速創(chuàng)建getter和setter方法

    IntelliJ IDEA快速創(chuàng)建getter和setter方法

    這篇文章主要介紹了IntelliJ IDEA快速創(chuàng)建getter和setter方法,本文通過圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-03-03

最新評論