日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

java类加载器_类加载器

發(fā)布時(shí)間:2024/10/8 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java类加载器_类加载器 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

回顧一下類(lèi)加載過(guò)程

類(lèi)加載過(guò)程:加載->連接->初始化。連接過(guò)程又可分為三步:驗(yàn)證->準(zhǔn)備->解析。

一個(gè)非數(shù)組類(lèi)的加載階段(加載階段獲取類(lèi)的二進(jìn)制字節(jié)流的動(dòng)作)是可控性最強(qiáng)的階段,這一步我們可以去完成還可以自定義類(lèi)加載器去控制字節(jié)流的獲取方式(重寫(xiě)一個(gè)類(lèi)加載器的 loadClass() 方法)。數(shù)組類(lèi)型不通過(guò)類(lèi)加載器創(chuàng)建,它由 Java 虛擬機(jī)直接創(chuàng)建。

所有的類(lèi)都由類(lèi)加載器加載,加載的作用就是將 .class文件加載到內(nèi)存。

類(lèi)加載器總結(jié)

JVM 中內(nèi)置了三個(gè)重要的 ClassLoader,除了 BootstrapClassLoader 其他類(lèi)加載器均由 Java 實(shí)現(xiàn)且全部繼承自java.lang.ClassLoader:

  • BootstrapClassLoader(啟動(dòng)類(lèi)加載器) :最頂層的加載類(lèi),由C++實(shí)現(xiàn),負(fù)責(zé)加載 %JAVA_HOME%/lib目錄下的jar包和類(lèi)或者或被 -Xbootclasspath參數(shù)指定的路徑中的所有類(lèi)。
  • ExtensionClassLoader(擴(kuò)展類(lèi)加載器) :主要負(fù)責(zé)加載目錄 %JRE_HOME%/lib/ext 目錄下的jar包和類(lèi),或被 java.ext.dirs 系統(tǒng)變量所指定的路徑下的jar包。
  • AppClassLoader(應(yīng)用程序類(lèi)加載器) :面向我們用戶(hù)的加載器,負(fù)責(zé)加載當(dāng)前應(yīng)用classpath下的所有jar包和類(lèi)。
  • 雙親委派模型

    雙親委派模型介紹

    每一個(gè)類(lèi)都有一個(gè)對(duì)應(yīng)它的類(lèi)加載器。系統(tǒng)中的 ClassLoder 在協(xié)同工作的時(shí)候會(huì)默認(rèn)使用 雙親委派模型 。即在類(lèi)加載的時(shí)候,系統(tǒng)會(huì)首先判斷當(dāng)前類(lèi)是否被加載過(guò)。已經(jīng)被加載的類(lèi)會(huì)直接返回,否則才會(huì)嘗試加載。加載的時(shí)候,首先會(huì)把該請(qǐng)求委派該父類(lèi)加載器的 loadClass() 處理,因此所有的請(qǐng)求最終都應(yīng)該傳送到頂層的啟動(dòng)類(lèi)加載器 BootstrapClassLoader 中。當(dāng)父類(lèi)加載器無(wú)法處理時(shí),才由自己來(lái)處理。當(dāng)父類(lèi)加載器為null時(shí),會(huì)使用啟動(dòng)類(lèi)加載器 BootstrapClassLoader 作為父類(lèi)加載器。

    每個(gè)類(lèi)加載都有一個(gè)父類(lèi)加載器,我們通過(guò)下面的程序來(lái)驗(yàn)證。

    public class ClassLoaderDemo {public static void main(String[] args) {System.out.println("ClassLodarDemo's ClassLoader is " + ClassLoaderDemo.class.getClassLoader());System.out.println("The Parent of ClassLodarDemo's ClassLoader is " + ClassLoaderDemo.class.getClassLoader().getParent());System.out.println("The GrandParent of ClassLodarDemo's ClassLoader is " + ClassLoaderDemo.class.getClassLoader().getParent().getParent());} }

    Output

    ClassLodarDemo's ClassLoader is sun.misc.Launcher$AppClassLoader@18b4aac2 The Parent of ClassLodarDemo's ClassLoader is sun.misc.Launcher$ExtClassLoader@1b6d3586 The GrandParent of ClassLodarDemo's ClassLoader is null

    AppClassLoader的父類(lèi)加載器為ExtClassLoader ExtClassLoader的父類(lèi)加載器為null,null并不代表ExtClassLoader沒(méi)有父類(lèi)加載器,而是 BootstrapClassLoader 。

    其實(shí)這個(gè)雙親翻譯的容易讓別人誤解,我們一般理解的雙親都是父母,這里的雙親更多地表達(dá)的是“父母這一輩”的人而已,并不是說(shuō)真的有一個(gè) Mother ClassLoader 和一個(gè) Father ClassLoader 。另外,類(lèi)加載器之間的“父子”關(guān)系也不是通過(guò)繼承來(lái)體現(xiàn)的,是由“優(yōu)先級(jí)”來(lái)決定。官方API文檔對(duì)這部分的描述如下:

    The Java platform uses a delegation model for loading classes. The basic idea is that every class loader has a “parent” class loader. When loading a class, a class loader first “delegates” the search for the class to its parent class loader before attempting to find the class itself.

    雙親委派模型實(shí)現(xiàn)源碼分析

    雙親委派模型的實(shí)現(xiàn)代碼非常簡(jiǎn)單,邏輯非常清晰,都集中在 java.lang.ClassLoader 的 loadClass() 中,相關(guān)代碼如下所示。

    private final ClassLoader parent; protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{synchronized (getClassLoadingLock(name)) {// 首先,檢查請(qǐng)求的類(lèi)是否已經(jīng)被加載過(guò)Class<?> c = findLoadedClass(name);if (c == null) {long t0 = System.nanoTime();try {if (parent != null) {//父加載器不為空,調(diào)用父加載器loadClass()方法處理c = parent.loadClass(name, false);} else {//父加載器為空,使用啟動(dòng)類(lèi)加載器 BootstrapClassLoader 加載c = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {//拋出異常說(shuō)明父類(lèi)加載器無(wú)法完成加載請(qǐng)求}if (c == null) {long t1 = System.nanoTime();//自己嘗試加載c = findClass(name);// this is the defining class loader; record the statssun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);sun.misc.PerfCounter.getFindClasses().increment();}}if (resolve) {resolveClass(c);}return c;}}

    雙親委派模型的好處

    雙親委派模型保證了Java程序的穩(wěn)定運(yùn)行,可以避免類(lèi)的重復(fù)加載(JVM 區(qū)分不同類(lèi)的方式不僅僅根據(jù)類(lèi)名,相同的類(lèi)文件被不同的類(lèi)加載器加載產(chǎn)生的是兩個(gè)不同的類(lèi)),也保證了 Java 的核心 API 不被篡改。如果沒(méi)有使用雙親委派模型,而是每個(gè)類(lèi)加載器加載自己的話(huà)就會(huì)出現(xiàn)一些問(wèn)題,比如我們編寫(xiě)一個(gè)稱(chēng)為 java.lang.Object 類(lèi)的話(huà),那么程序運(yùn)行的時(shí)候,系統(tǒng)就會(huì)出現(xiàn)多個(gè)不同的 Object 類(lèi)。

    如果我們不想用雙親委派模型怎么辦?

    為了避免雙親委托機(jī)制,我們可以自己定義一個(gè)類(lèi)加載器,然后重寫(xiě) loadClass() 即可。

    完善修正(issue871:類(lèi)加載器一問(wèn)的補(bǔ)充說(shuō)明):

    自定義加載器的話(huà),需要繼承 ClassLoader 。如果我們不想打破雙親委派模型,就重寫(xiě) ClassLoader 類(lèi)中的 findClass() 方法即可,無(wú)法被父類(lèi)加載器加載的類(lèi)最終會(huì)通過(guò)這個(gè)方法被加載。但是,如果想打破雙親委派模型則需要重寫(xiě) loadClass() 方法

    自定義類(lèi)加載器

    除了 BootstrapClassLoader 其他類(lèi)加載器均由 Java 實(shí)現(xiàn)且全部繼承自java.lang.ClassLoader。如果我們要自定義自己的類(lèi)加載器,很明顯需要繼承 ClassLoader。

    推薦閱讀

    • 深入分析Java ClassLoader原理
    • 《2020最新Java基礎(chǔ)精講視頻教程和學(xué)習(xí)路線(xiàn)!》
    • 老大難的 Java ClassLoader 再不理解就老了
    • Java類(lèi)加載器(ClassLoader)
    作者:Snailclimb
    鏈接:類(lèi)加載器
    來(lái)源:github

    總結(jié)

    以上是生活随笔為你收集整理的java类加载器_类加载器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。