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

Java類加載策略之雙親委派機(jī)制全面分析講解

 更新時(shí)間:2023年12月30日 11:44:13   作者:小王篤定前行  
這篇文章主要介紹了Java雙親委派機(jī)制,雙親委派模型是Java加載類的機(jī)制,采用雙親委派模型的好處是Java類隨著它的類加載器一起具備了一種帶有優(yōu)先級(jí)的層級(jí)關(guān)系,通過(guò)這種層級(jí)關(guān)系可以避免類的重復(fù)加載,感興趣的朋友可以參考下

前言

ava虛擬機(jī)(JVM)的類加載機(jī)制是Java應(yīng)用中不可或缺的一部分。本文將詳細(xì)介紹JVM的雙親委派機(jī)制,并闡述各關(guān)鍵點(diǎn)。

一、什么是雙親委派機(jī)制

雙親委派機(jī)制(Parent-Delegate Model)是Java類加載器中采用的一種類加載策略。該機(jī)制的核心思想是:如果一個(gè)類加載器收到了類加載請(qǐng)求,默認(rèn)先將該請(qǐng)求委托給其父類加載器處理。只有當(dāng)父級(jí)加載器無(wú)法加載該類時(shí),才會(huì)嘗試自行加載。

二、類加載器與層級(jí)關(guān)系

Java中的類加載器主要有如下三種:

  • 啟動(dòng)類加載器(Bootstrap ClassLoader): 負(fù)責(zé)加載 %JAVA_HOME%/jre/lib 目錄下的核心Java類庫(kù)如 rt.jar、charsets.jar 等。
  • 擴(kuò)展類加載器(Extension ClassLoader): 負(fù)責(zé)加載 %JAVA_HOME%/jre/lib/ext 目錄下的擴(kuò)展類庫(kù)。
  • 應(yīng)用類加載器(Application ClassLoader): 負(fù)責(zé)加載用戶類路徑(ClassPath)下的應(yīng)用程序類。

這三種類加載器之間存在父子層級(jí)關(guān)系。啟動(dòng)類加載器是最高級(jí)別的加載器,沒(méi)有父加載器;擴(kuò)展類加載器的父加載器是啟動(dòng)類加載器;應(yīng)用類加載器的父加載器是擴(kuò)展類加載器。

  除了以上三個(gè)內(nèi)置類加載器,用戶還可以通過(guò)繼承 java.lang.ClassLoader 類自定義類加載器,根據(jù)實(shí)際需求處理類加載請(qǐng)求。

三、雙親委派機(jī)制作用及如何破環(huán)機(jī)制

通過(guò)上述兩塊內(nèi)容,我們對(duì)雙親委派機(jī)制、加載流程及層級(jí)有了一些了解,這時(shí)我們不妨拋出幾個(gè)疑問(wèn)。

  • 為什么需要雙親委派
  • 雙親委派機(jī)制有哪些優(yōu)缺點(diǎn)
  • 如何打破這個(gè)機(jī)制
  • 有哪些工具選擇了破壞機(jī)制。

為什么需要雙親委派

1. 通過(guò)雙親委派機(jī)制,可以避免類的重復(fù)加載,當(dāng)父加載器已經(jīng)加載過(guò)某一個(gè)類時(shí),子加載器就不會(huì)再重新加載這個(gè)類。

2. 通過(guò)雙親委派機(jī)制,可以保證安全性。因?yàn)锽ootstrapClassLoader在加載的時(shí)候,只會(huì)加載JAVA_HOME中的jar包里面的類,如java.lang.String,那么這個(gè)類是不會(huì)被隨意替換的。

那么,就可以避免有人自定義一個(gè)有破壞功能的java.lang.String被加載。這樣可以有效的防止核心Java API被篡改。

這是在JDK1.8的java.lang.ClassLoader類中的源碼,這個(gè)方法就是用于加載指定的類。

實(shí)現(xiàn)雙親委派機(jī)制 的代碼也都集中在這個(gè)方法之中:

protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException{
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                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.
                    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;
        }
    }

通過(guò)以上代碼得出結(jié)論:

  • 當(dāng)類加載器接收到類加載的請(qǐng)求時(shí),首先檢查該類是否已經(jīng)被當(dāng)前類加載器加載;
  • 若該類未被加載過(guò),當(dāng)前類加載器會(huì)將加載請(qǐng)求委托給父類加載器去完成;
  • 若當(dāng)前類加載器的父類加載器為null,會(huì)委托啟動(dòng)類加載器完成加載;
  • 若父類加載器無(wú)法完成類的加載,當(dāng)前類加載器才會(huì)去嘗試加載該類。

雙親委派機(jī)制的優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

  • 避免重復(fù)加載:由于類加載器直接從父類加載器那里加載類,避免了類的重復(fù)加載。
  • 提高安全性:通過(guò)雙親委派模型,Java 標(biāo)準(zhǔn)庫(kù)中的核心類庫(kù)(如 java.lang.*)由啟動(dòng)類加載器加載,這樣能保證這些核心類庫(kù)不會(huì)被惡意代碼篡改或替換,從而提高程序的安全性。
  • 保持類加載的一致性:這種方式確保了同一個(gè)類的加載由同一個(gè)類加載器完成,從而在運(yùn)行時(shí)保證了類型的唯一性和相同性。這也有助于減輕類加載器在處理相互關(guān)聯(lián)的類時(shí)的復(fù)雜性。

缺點(diǎn):

  • 靈活性降低:由于類加載的過(guò)程需要不斷地委托給父類加載器,這種機(jī)制可能導(dǎo)致實(shí)際應(yīng)用中類加載的靈活性降低。
  • 增加了類加載時(shí)間:在類加載的過(guò)程中,需要不斷地查詢并委托父類加載器,這意味著類加載所需要的時(shí)間可能會(huì)增加。在類數(shù)量龐大或類加載器層次比較深的情況下,這種時(shí)間延遲可能會(huì)變得更加明顯。

如何打破這個(gè)機(jī)制

既然上述文章中我們已經(jīng)知道了雙親委派的實(shí)現(xiàn)方式,那么如何打破這個(gè)機(jī)制呢。

想要破壞這種機(jī)制,那么就需要自定義一個(gè)類加載器,繼承ClassLoader類重寫(xiě)其中的loadClass方法,使其不進(jìn)行雙親委派即可。

寫(xiě)個(gè)示例

import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Paths;
public class CustomClassLoader extends ClassLoader {
    // 自定義類加載器必須提供一個(gè)加載類文件的位置
    private String classesPath;
    public CustomClassLoader(String classesPath, ClassLoader parent) {
        super(parent);
        this.classesPath = classesPath;
    }
    @Override
    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        //首先,檢查已加載的類
        Class<?> loadedClass = findLoadedClass(name);
        if (loadedClass == null) {
            // 如果已加載類中沒(méi)有該類, 嘗試用自定義的方法加載
            try {
                loadedClass = findClassInPath(name);
            } catch (ClassNotFoundException e) {
                // 如果自定義加載方法找不到類,則委托給父類加載器
                loadedClass = super.loadClass(name, resolve);
            }
        }
        if (resolve) {
            resolveClass(loadedClass);
        }
        return loadedClass;
    }
    private Class<?> findClassInPath(String className) throws ClassNotFoundException {
        try {
            String filePath = className.replace('.', '/') + ".class";
            byte[] classBytes = Files.readAllBytes(Paths.get(classesPath, filePath));
            return defineClass(className, classBytes, 0, classBytes.length);
        } catch (Exception e) {
            throw new ClassNotFoundException("Class not found in classes path: " + className, e);
        }
    }
    public static void main(String[] args) throws Exception {
        String pathToClasses = "/path/to/your/classes";
        String className = "com.example.SampleClass";
        String methodName = "sampleMethod";
        // 創(chuàng)建自定義類加載器實(shí)例,將類的加載權(quán)交給它
        CustomClassLoader customClassLoader = new CustomClassLoader(pathToClasses, CustomClassLoader.class.getClassLoader());
        // 使用自定義類加載器加載類
        Class<?> customClass = customClassLoader.loadClass(className);
        // 創(chuàng)建類的實(shí)例并調(diào)用方法
        Object obj = customClass.newInstance();
        Method method = customClass.getDeclaredMethod(methodName);
        method.setAccessible(true);
        method.invoke(obj);
    }
}

上面的示例代碼中,我們重寫(xiě)了 loadClass 方法,先嘗試通過(guò) findClassInPath 從指定的路徑加載類,如果無(wú)法加載就委托給父類加載器。這樣,我們就實(shí)現(xiàn)了打破雙親委派機(jī)制的自定義類加載器。

以下是代碼的詳細(xì)解析:

  • 自定義類加載器 CustomClassLoader 繼承 Java ClassLoader 類。
  • 在類加載器的構(gòu)造方法中設(shè)置自定義類加載器的類路徑 classesPath 和父加載器 parent
  • 重寫(xiě) loadClass 方法。首先檢查已加載的類,如果已加載則返回。否則嘗試用自定義的方法在 classesPath 中加載類。如果自定義加載方法找不到類,則委托給父類加載器。
  • 實(shí)現(xiàn)名為 findClassInPath 的自定義加載方法。這個(gè)方法使用類名 classNameclassesPath 指定的目錄下查找對(duì)應(yīng)的 .class 文件,然后將文件內(nèi)容讀取為字節(jié)數(shù)組并調(diào)用 defineClass 方法,將其轉(zhuǎn)換為 Java 類的 Class 對(duì)象。如果類不存在或出現(xiàn)其他錯(cuò)誤,會(huì)拋出 ClassNotFoundException 異常。
  • 在 main 方法中,創(chuàng)建一個(gè) CustomClassLoader 類的實(shí)例。將類的加載任務(wù)交給自定義類加載器,指定加載路徑和要加載的類。
  • 使用自定義類加載器加載目標(biāo)類,創(chuàng)建類的實(shí)例,并調(diào)用指定方法。

有哪些工具選擇了破壞機(jī)制

既然在上文中,我們已經(jīng)清楚怎么打破雙親機(jī)制,那么有哪些工具選擇了破壞機(jī)制呢?為什么?

  • OSGi(Open Service Gateway Initiative):OSGi 是一個(gè)模塊化系統(tǒng)和服務(wù)平臺(tái),提供了一個(gè)強(qiáng)大的類加載器模型。在 OSGi 中,每個(gè)模塊都有一個(gè)獨(dú)立的類加載器,可以按需加載來(lái)自不同模塊的類。這有助于解決 JAR 地獄問(wèn)題,提高模塊化和動(dòng)態(tài)更新能力。
  • Tomcat Web容器:Tomcat 的 Web 應(yīng)用類加載器可以加載 Web 應(yīng)用程序中的本地類庫(kù),從而使得每個(gè) Web 應(yīng)用程序可以使用各自的版本的類庫(kù)。這些 Web 應(yīng)用的類加載器都是${tomcat-home}/lib 中類庫(kù)的子類加載器。
  • Java Agent: Java Agent 是一種基于 Java Instrumentation API 的技術(shù),它可以在運(yùn)行時(shí)修改已加載的類的字節(jié)碼,從而實(shí)現(xiàn)類的熱替換、AOP(面向切面編程)等功能。這種技術(shù)在諸如熱部署、性能監(jiān)控和分布式追蹤等場(chǎng)景中有廣泛應(yīng)用。
  • JDK 中的 URLClassLoader:JDK 自帶的 URLClassLoader 可以用來(lái)加載指定 URL 路徑下的類。實(shí)際上,它實(shí)現(xiàn)了一種子類優(yōu)先的策略,先嘗試加載自身路徑下的類,再委托給父類加載器,從而打破了雙親委派機(jī)制。

這些工具和技術(shù)之所以要打破雙親委派機(jī)制,主要是出于以下原因:

  • 實(shí)現(xiàn)模塊化和動(dòng)態(tài)更新:例如 OSGi,通過(guò)獨(dú)立的類加載器實(shí)現(xiàn)不同模塊間解耦,并支持模塊的動(dòng)態(tài)卸載和更新。
  • 解決類庫(kù)版本沖突(JAR地獄問(wèn)題):在復(fù)雜系統(tǒng)中,不同模塊可能依賴不同版本的類庫(kù)。為避免版本沖突,可使用獨(dú)立的類加載器,使它們分別加載各自的類庫(kù)版本。
  • 運(yùn)行時(shí)修改類:Java Agent 可以在運(yùn)行時(shí)修改類字節(jié)碼,從而支持熱替換、AOP 和性能監(jiān)控等功能。
  • 支持 Web 應(yīng)用程序的獨(dú)立部署和更新:例如 Tomcat,可以為每個(gè) Web 應(yīng)用程序分配一個(gè)獨(dú)立的類加載器,實(shí)現(xiàn)各自部署與更新。

需要注意的是,打破雙親委派機(jī)制可能會(huì)帶來(lái)類加載沖突、安全性和性能等問(wèn)題,因此在實(shí)際應(yīng)用中要謹(jǐn)慎使用。

四、總結(jié)

本文介紹了JVM的雙親委派機(jī)制,包括概念、類加載器層級(jí)關(guān)系、雙親委派流程及實(shí)例分析等方面的內(nèi)容。雙親委派機(jī)制可以確保Java應(yīng)用類型安全,同時(shí)避免類加載沖突。在某些特定場(chǎng)景下,我們可以通過(guò)自定義類加載器對(duì)類加載策略進(jìn)行調(diào)整,以滿足應(yīng)用特性和性能需求。

以上就是Java雙親委派機(jī)制全面分析講解的詳細(xì)內(nèi)容,更多關(guān)于Java雙親委派機(jī)制的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • JAVA8獲取list集合中重復(fù)的元素與獲取去重?cái)?shù)據(jù)實(shí)例

    JAVA8獲取list集合中重復(fù)的元素與獲取去重?cái)?shù)據(jù)實(shí)例

    這篇文章主要給大家介紹了關(guān)于JAVA8獲取list集合中重復(fù)的元素與獲取去重?cái)?shù)據(jù)的相關(guān)資料,在實(shí)際開(kāi)發(fā)中經(jīng)常會(huì)遇到需要找出(刪除)一個(gè)list中某些元素的屬性相同的元素,需要的朋友可以參考下
    2023-07-07
  • Java高效實(shí)現(xiàn)excel轉(zhuǎn)pdf(支持帶圖片的轉(zhuǎn)換)

    Java高效實(shí)現(xiàn)excel轉(zhuǎn)pdf(支持帶圖片的轉(zhuǎn)換)

    這篇文章主要為大家詳細(xì)介紹了如何用java實(shí)現(xiàn)excel轉(zhuǎn)pdf文件,并且支持excel單元格中帶有圖片的轉(zhuǎn)換,文中的示例代碼講解詳細(xì),需要的可以參考下
    2024-01-01
  • Java 大小寫(xiě)最快轉(zhuǎn)換方式實(shí)例代碼

    Java 大小寫(xiě)最快轉(zhuǎn)換方式實(shí)例代碼

    這篇文章主要介紹了Java 大小寫(xiě)最快轉(zhuǎn)換方式實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下
    2017-07-07
  • Java定時(shí)任務(wù)詳解

    Java定時(shí)任務(wù)詳解

    定時(shí)任務(wù)在項(xiàng)目中經(jīng)常會(huì)使用到,本文主要根據(jù)博主自己使用定時(shí)的經(jīng)驗(yàn)分如下幾點(diǎn)介紹定時(shí)任務(wù):1、Quartz定時(shí)任務(wù)簡(jiǎn)介及Spring配置Quartz定時(shí)任務(wù);2、SchedulerFactory對(duì)定時(shí)任務(wù)進(jìn)行增刪改查
    2017-04-04
  • Spring Boot中的Properties的使用詳解

    Spring Boot中的Properties的使用詳解

    這篇文章主要介紹了Spring Boot中的Properties的使用詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • 修改idea運(yùn)行內(nèi)存大小的方法總結(jié)

    修改idea運(yùn)行內(nèi)存大小的方法總結(jié)

    在開(kāi)發(fā)過(guò)程中,總會(huì)遇到idea運(yùn)行內(nèi)存不足,所以本文小編給大家介紹了修改idea運(yùn)行內(nèi)存大小的兩種方法,文中通過(guò)圖文給大家講解的非常詳細(xì),需要的朋友可以參考下
    2023-12-12
  • Spring計(jì)劃任務(wù)用法實(shí)例詳解

    Spring計(jì)劃任務(wù)用法實(shí)例詳解

    這篇文章主要介紹了Spring計(jì)劃任務(wù)用法,結(jié)合實(shí)例形式詳細(xì)分析了spring計(jì)劃任務(wù)相關(guān)原理、配置、使用方法及操作注意事項(xiàng),需要的朋友可以參考下
    2019-11-11
  • Java?Web?Axios實(shí)現(xiàn)前后端數(shù)據(jù)異步交互實(shí)例代碼

    Java?Web?Axios實(shí)現(xiàn)前后端數(shù)據(jù)異步交互實(shí)例代碼

    Axios作為一個(gè)流行的前端?HTTP?通信庫(kù),可以極大地簡(jiǎn)化前端與后端之間的數(shù)據(jù)交互,這篇文章主要介紹了Java?Web?Axios實(shí)現(xiàn)前后端數(shù)據(jù)異步交互的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-09-09
  • IntelliJ IDEA本地代碼提交到github網(wǎng)站不顯示與本地不同步問(wèn)題的解決辦法

    IntelliJ IDEA本地代碼提交到github網(wǎng)站不顯示與本地不同步問(wèn)題的解決辦法

    今天小編就為大家分享一篇關(guān)于IntelliJ IDEA本地代碼提交到github網(wǎng)站不顯示與本地不同步問(wèn)題的解決辦法,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-10-10
  • Spring Boot 的注解生效詳細(xì)步驟解析

    Spring Boot 的注解生效詳細(xì)步驟解析

    Spring通過(guò)掃描、解析、注冊(cè)分層處理配置類注解(如@Configuration、@ComponentScan等),利用遞歸、延遲加載和緩存機(jī)制,實(shí)現(xiàn)BeanDefinition的動(dòng)態(tài)注冊(cè)與靈活擴(kuò)展,解決依賴和性能問(wèn)題,本文給大家介紹Spring Boot的注解生效詳細(xì)步驟解析,感興趣的朋友跟隨小編一起看看吧
    2025-09-09

最新評(píng)論

和龙市| 洪湖市| 油尖旺区| 井研县| 平顺县| 永兴县| 甘泉县| 沽源县| 乌什县| 凉山| 盐山县| 古浪县| 十堰市| 土默特右旗| 棋牌| 来宾市| 客服| 牡丹江市| 汉川市| 鸡东县| 景泰县| 广饶县| 山阴县| 公安县| 武夷山市| 景宁| 商丘市| 神木县| 元氏县| 墨竹工卡县| 仪征市| 吉安市| 沙湾县| 江口县| 河南省| 合川市| 白玉县| 柯坪县| 屏山县| 开江县| 阿合奇县|