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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

为何采用双亲委派机制

發布時間:2024/2/28 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 为何采用双亲委派机制 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、雙親(父親)委派機制

java中存在3種類型的類加載器:引導類加載器,擴展類加載器和系統類加載器。三者是的關系是:引導類加載器是擴展類加載器的父類,擴展類加載器是系統類加載器的父類。

  • 引導類加載器(BootStrap)
    主要負責加載jvm自身所需要的類,該加載器由C++實現,加載的是<JAVA_HOME>/lib下的class文件,或-Xbootclasspath參數指定的路徑下的jar包加載到內存中,注意必由于虛擬機是按照文件名識別加載jar包的,如rt.jar,如果文件名不被虛擬機識別,即使把jar包丟到lib目錄下也是沒有作用的(出于安全考慮,Bootstrap啟動類加載器只加載包名為java、javax、sun等開頭的類)。
  • 拓展類加載器(Extension)
    擴展類加載器是指Sun公司(已被Oracle收購)實現的sun.misc.Launcher$ExtClassLoader類,由Java語言實現的,是Launcher的靜態內部類,它負責加載<JAVA_HOME>/lib/ext目錄下或者由系統變量-Djava.ext.dir指定位路徑中的類庫,開發者可以直接使用標準擴展類加載器。
java源碼 在sun.misc.Launcher private static File[] getExtDirs() {String var0 = System.getProperty("java.ext.dirs");File[] var1;if (var0 != null) {StringTokenizer var2 = new StringTokenizer(var0, File.pathSeparator);int var3 = var2.countTokens();var1 = new File[var3];for(int var4 = 0; var4 < var3; ++var4) {var1[var4] = new File(var2.nextToken());}} else {var1 = new File[0];}return var1;}
  • 系統類加載器
    也稱應用程序加載器是指 Sun公司實現的sun.misc.Launcher$AppClassLoader。它負責加載系統類路徑java -classpath或-D java.class.path指定路徑下的類庫,也就是我們經常用到的classpath路徑,開發者可以直接使用系統類加載器,一般情況下該類加載是程序中默認的類加載器,通過ClassLoade.getSystemClassLoader()方法可以獲取到該類加載器。
static class AppClassLoader extends URLClassLoader {final URLClassPath ucp = SharedSecrets.getJavaNetAccess().getURLClassPath(this);public static ClassLoader getAppClassLoader(final ClassLoader var0) throws IOException {final String var1 = System.getProperty("java.class.path");final File[] var2 = var1 == null ? new File[0] : Launcher.getClassPath(var1);return (ClassLoader)AccessController.doPrivileged(new PrivilegedAction<Launcher.AppClassLoader>() {public Launcher.AppClassLoader run() {URL[] var1x = var1 == null ? new URL[0] : Launcher.pathToURLs(var2);return new Launcher.AppClassLoader(var1x, var0);}});}...

在Java的日常應用程序開發中,類的加載幾乎是由上述3種類加載器相互配合執行的,在必要時,我們還可以自定義類加載器,需要注意的是,Java虛擬機對class文件采用的是按需加載的方式,也就是說當需要使用該類時才會將它的class文件加載到內存生成class對象,而且加載某個類的class文件時,Java虛擬機采用的是雙親委派模式即把請求交由父類處理,它一種任務委派模式,下面我們進一步了解它。

二、目的

  • 首先明確一點:jvm如何認定兩個對象同屬于一個類型,必須同時滿足下面兩個條件:
    • 都是用同名的類完成實例化的。
    • 兩個實例各自對應的同名的類的加載器必須是同一個。比如兩個相同名字的類,一個是用系統加載器加載的,一個擴展類加載器加載的,兩個類生成的對象將被jvm認定為不同類型的對象。
  • 所以,為了系統類的安全,類似“ java.lang.Object”這種核心類,jvm需要保證他們生成的對象都會被認定為同一種類型。即“通過代理模式,對于 Java 核心庫的類的加載工作由引導類加載器來統一完成,保證了 Java 應用所使用的都是同一個版本的 Java 核心庫的類,是互相兼容的”。

  • 面試題:
    能不能自己寫個類叫java.lang.System?

    答案:通常不可以,但可以采取另類方法達到這個需求。

    解釋:為了不讓我們寫System類,類加載采用委托機制,這樣可以保證爸爸們優先,爸爸們能找到的類,兒子就沒有機會加載。而System類是Bootstrap加載器加載的,就算自己重寫,也總是使用Java系統提供的System,自己寫的System類根本沒有機會得到加載。
    但是,我們可以自己定義一個類加載器來達到這個目的,為了避免雙親委托機制,這個類加載器也必須是特殊的。由于系統自帶的三個類加載器都加載特定目錄下的類,如果我們自己的類加載器加載一個特殊的目錄,那么系統的加載器就無法加載,也就是最終還是由我們自己的加載器加載

    ------------------------------------------------------------------------------------------------------------------------------------------------------

    什么是雙親委派機制

    當某個類加載器需要加載某個.class文件時,它首先把這個任務委托給他的上級類加載器,遞歸這個操作,如果上級的類加載器沒有加載,自己才會去加載這個類。

    類加載器的類別

    BootstrapClassLoader(啟動類加載器)

    c++編寫,加載java核心庫 java.*,構造ExtClassLoader和AppClassLoader。由于引導類加載器涉及到虛擬機本地實現細節,開發者無法直接獲取到啟動類加載器的引用,所以不允許直接通過引用進行操作

    ExtClassLoader (標準擴展類加載器)

    java編寫,加載擴展庫,如classpath中的jre ,javax.*或者
    java.ext.dir 指定位置中的類,開發者可以直接使用標準擴展類加載器。

    AppClassLoader(系統類加載器)

    java編寫,加載程序所在的目錄,如user.dir所在的位置的class

    CustomClassLoader(用戶自定義類加載器)

    java編寫,用戶自定義的類加載器,可加載指定路徑的class文件

    源碼分析

    ?

    protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{synchronized (getClassLoadingLock(name)) {// 首先檢查這個classsh是否已經加載過了Class<?> c = findLoadedClass(name);if (c == null) {long t0 = System.nanoTime();try {// c==null表示沒有加載,如果有父類的加載器則讓父類加載器加載if (parent != null) {c = parent.loadClass(name, false);} else {//如果父類的加載器為空 則說明遞歸到bootStrapClassloader了//bootStrapClassloader比較特殊無法通過get獲取c = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {}if (c == null) {//如果bootstrapClassLoader 仍然沒有加載過,則遞歸回來,嘗試自己去加載classlong 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;}}

    委派機制的流程圖

    image.png

    雙親委派機制的作用

    1、防止重復加載同一個.class。通過委托去向上面問一問,加載過了,就不用再加載一遍。保證數據安全。
    2、保證核心.class不能被篡改。通過委托方式,不會去篡改核心.clas,即使篡改也不會去加載,即使加載也不會是同一個.class對象了。不同的加載器加載同一個.class也不是同一個Class對象。這樣保證了Class執行安全。



    作者:秦時的明月夜
    鏈接:https://www.jianshu.com/p/1e4011617650
    來源:簡書
    著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。

    總結

    以上是生活随笔為你收集整理的为何采用双亲委派机制的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。