一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|編程技術|正則表達式|C/C++|

服務器之家 - 編程語言 - JAVA教程 - 整理Java中的ClassLoader核心知識點

整理Java中的ClassLoader核心知識點

2020-11-06 23:41今日頭條SapphireCoder JAVA教程

本文整理了基于 JDK8 的 ClassLoader 核心知識點,包括 JVM 中 ClassLoader 種類、ClassLoader 執行順序、父加載器概念、雙親委派機制、自定義類加載器。

本文整理了基于 JDK8 的 ClassLoader 核心知識點,包括 JVM 中 ClassLoader 種類、ClassLoader 執行順序、父加載器概念、雙親委派機制、自定義類加載器。

整理Java中的ClassLoader核心知識點

JDK 和 JRE 的作用

  • JDK 提供了 java 的編程環境,它包含編譯調試的環境功能,包含 JRE(JDK 目錄中的 JRE 為專用 JRE,而安裝后與 JDK 同目錄的 JRE 為公用 JRE)。開發時一般運行的是 JDK 專用JRE,而運行外部程序時一般運行的是公用 JRE,實現了分工不同的 jre 負責各自范圍的內容。
  • JRE 提供了 JAVA 程序運行的必要環境平臺

JAVAHOME、PATH、CLASSPATH

  • JAVAHOME: JDK安裝的位置路徑,如:D:\Program Files\Java\jdk1.8.0_241
  • PATH: 配置后運行 bin 中的命令不需要補全全路徑,如可以在任意的位置運行 java 和 javac 命令, %JAVA_HOME%\bin;
  • CLASSPATH:指向jar包路徑 %JAVA_HOME%\lib;

類加載器的種類

在JVM中有三類ClassLoader構成:

  • Bootstrap ClassLoader 啟動類(或根類)加載器
  • Extention ClassLoader 擴展的類加載器
  • Appclass Loader 應用類加載器
整理Java中的ClassLoader核心知識點

(1) Bootstrap ClassLoader

Bootstrap ClassLoader 最頂層的類加載器,主要加載核心類庫 %JRE_HOME%\lib 下的 rt.jar、resources.jar、charsets.jar 和 class文件等。

//執行 

System.out.println(System.getProperty("sun.boot.class.path")); 

//輸出結果 

D:\Program Files\Java\jdk1.8.0_241\jre\lib\resources.jar; 

D:\Program Files\Java\jdk1.8.0_241\jre\lib\rt.jar; 

D:\Program Files\Java\jdk1.8.0_241\jre\lib\sunrsasign.jar; 

D:\Program Files\Java\jdk1.8.0_241\jre\lib\jsse.jar; 

D:\Program Files\Java\jdk1.8.0_241\jre\lib\jce.jar; 

D:\Program Files\Java\jdk1.8.0_241\jre\lib\charsets.jar; 

D:\Program Files\Java\jdk1.8.0_241\jre\lib\jfr.jar; 

D:\Program Files\Java\jdk1.8.0_241\jre\classes 

(2) Extention ClassLoader

Extention ClassLoader 擴展的類加載器,主要加載目錄 %JRE_HOME%\lib\ext 目錄下的jar包和class文件。

//執行 

System.out.println(System.getProperty("java.ext.dirs")); 

//輸出 

D:\Program Files\Java\jdk1.8.0_241\jre\lib\ext;C:\Windows\Sun\Java\lib\ext 

(3) Appclass Loader

Appclass Loader也稱為SystemAppClass 加載當前應用的classpath的所有類。

類加載器的執行順序

除啟動類加載器(Bootstrap ClassLoader)外,擴展類加載器和應用類加載器都是通過類sun.misc.Launcher進行初始化,而Launcher類則由啟動類加載器進行加載。Launcher相關代碼如下:

public Launcher() { 

    Launcher.ExtClassLoader var1; 

    try { 

        //初始化擴展類加載器,構造函數沒有入參,無法獲取啟動類加載器 

        var1 = Launcher.ExtClassLoader.getExtClassLoader(); 

    } catch (IOException var10) { 

        throw new InternalError("Could not create extension class loader", var10); 

    } 

 

    try { 

        //初始化應用類加載器,入參為擴展類加載器 

        this.loader = Launcher.AppClassLoader.getAppClassLoader(var1); 

    } catch (IOException var9) { 

        throw new InternalError("Could not create application class loader", var9); 

    } 

 

    // 設置上下文類加載器 

    Thread.currentThread().setContextClassLoader(this.loader); 

     

   //... 

加載順序:Bootstrap CLassloder > Extention ClassLoader > AppClassLoader

父加載器概念

AppClassLoader 和 ExtClassLoader 都繼承了 URLClassLoader。每個類加載器都有一個父加載器(注意:父類和父加載器是兩個不同的概念),可通過 getParent() 獲取父類加載器。

System.out.println("ClassLoader is:"+cl.toString()); 

System.out.println("ClassLoader\'s parent is:"+cl.getParent().toString());System.out.println("ClassLoader\'s grand father is:"+cl.getParent().getParent().toString()); 

  • AppClassLoader 的父加載器是ExtClassLoader
  • ExtClassLoader的父加載器是Bootstrap ClassLoader(上面代碼輸出 ExtClassLoader 為null 是因為 Bootstrap ClassLoader 本身不是一個Java 類所致)
  • Bootstrap ClassLoader是由C/C++編寫的,它本身是虛擬機的一部分,所以它并不是一個JAVA類,也就是無法在java代碼中獲取它的引用,JVM啟動時通過Bootstrap類加載器加載rt.jar等核心jar包中的class文件,之前的int.class,String.class都是由它加載。然后呢,我們前面已經分析了,JVM初始化sun.misc.Launcher并創建Extension ClassLoader和AppClassLoader實例。并將ExtClassLoader設置為AppClassLoader的父加載器。Bootstrap沒有父加載器,但是它卻可以作用一個ClassLoader的父加載器。

雙親委派

雙親委派模型:當一個類加載器接收到類加載請求時,會先請求其父類加載器加載,依次遞歸,當父類加載器無法找到該類時(根據類的全限定名稱),子類加載器才會嘗試去加載。

整理Java中的ClassLoader核心知識點

整理Java中的ClassLoader核心知識點

時序圖

為什么使用雙親委派模型?

雙親委派模型是為了保證Java核心庫的類型安全。所有Java應用都至少需要引用java.lang.Object類,在運行時這個類需要被加載到Java虛擬機中。如果該加載過程由自定義類加載器來完成,可能就會存在多個版本的java.lang.Object類,而且這些類之間是不兼容的。

通過雙親委派模型,對于Java核心庫的類的加載工作由啟動類加載器來統一完成,保證了Java應用所使用的都是同一個版本的Java核心庫的類,是互相兼容的。

自定義類加載器

不管是Bootstrap ClassLoader還是ExtClassLoader等,這些類加載器都只是加載指定的目錄下的jar包或者資源。如果我們需要動態加載比如從指定目錄中加載一個class文件,這時候通過自定義類加載器可以實現。

自定義類加載器只需要繼承java.lang.ClassLoader類,然后重寫findClass(String name)方法即可,在方法中指明如何獲取類的字節碼流。如果要破壞雙親委派規范的話,還需重寫loadClass方法(雙親委派的具體邏輯實現)。但不建議這么做。

public class ClassLoaderTest extends ClassLoader { 

 

    private String classPath; 

 

    public ClassLoaderTest(String classPath) { 

        this.classPath = classPath; 

    } 

 

    /** 

     * 編寫findClass方法的邏輯 

     * 

     * @param name 

     * @return 

     * @throws ClassNotFoundException 

     */ 

    @Override 

    protected Class<?> findClass(String name) throws ClassNotFoundException { 

        // 獲取類的class文件字節數組 

        byte[] classData = getClassData(name); 

        if (classData == null) { 

            throw new ClassNotFoundException(); 

        } else { 

            // 生成class對象 

            return defineClass(name, classData, 0, classData.length); 

        } 

    } 

 

    /** 

     * 編寫獲取class文件并轉換為字節碼流的邏輯 

     * 

     * @param className 

     * @return 

     */ 

    private byte[] getClassData(String className) { 

        // 讀取類文件的字節 

        String path = classNameToPath(className); 

        try { 

            InputStream is = new FileInputStream(path); 

            ByteArrayOutputStream stream = new ByteArrayOutputStream(); 

            byte[] buffer = new byte[2048]; 

            int num = 0

            // 讀取類文件的字節碼 

            while ((num = is.read(buffer)) != -1) { 

                stream.write(buffer, 0, num); 

            } 

            return stream.toByteArray(); 

        } catch (IOException e) { 

            e.printStackTrace(); 

        } 

        return null; 

    } 

 

    /** 

     * 類文件的完全路徑 

     * 

     * @param className 

     * @return 

     */ 

    private String classNameToPath(String className) { 

        return classPath + File.separatorChar 

                + className.replace('.', File.separatorChar) + ".class"; 

    } 

 

    public static void main(String[] args) { 

        String classPath = "/Users/zzs/my/article/projects/java-stream/src/main/java/"

        ClassLoaderTest loader = new ClassLoaderTest(classPath); 

 

        try { 

            //加載指定的class文件 

            Class<?> object1 = loader.loadClass("com.secbro2.classload.SubClass"); 

            System.out.println(object1.newInstance().toString()); 

        } catch (Exception e) { 

            e.printStackTrace(); 

        } 

    } 

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 99久精品| 天天舔天天操天天干 | 日本制服丝袜 | 国产伦精品一区二区三区免 | www.精品在线 | 欧美同志video 在线观看 | 成人综合婷婷国产精品久久免费 | 国产一区二区不卡视频 | 亚洲福利一区二区三区 | 国产午夜亚洲精品 | 精品国产91久久久久久久 | 亚洲无线一二三四区 | 午夜欧美福利视频 | 亚洲高清国产拍精品动图 | 成人精品一区久久久久 | a黄毛片| 91影视在线看免费观看 | 草莓视频网站18勿进 | 免费真实播放国产乱子伦 | 好吊色青青青国产综合在线观看 | 亚洲午夜久久久久久91 | 午夜dj免费视频观看社区 | 无限观看社区在线视频 | 欧美日韩高清完整版在线观看免费 | 美女69xx | 国产麻豆91欧美一区二区 | 国产亚洲女在线精品 | 日韩一区二区三区在线 | 色哟哟国产成人精品 | 免费观看一级一片 | japanesexxxx日本妞 | 欧美日本一本线在线观看 | naruto tube18动漫| 四虎综合九九色九九综合色 | 好大好深好涨好烫还要 | 久久久久999 | 轻轻色在线视频中文字幕 | 欧美成人aa| 亚洲xxxxxhd奶水女人 | 久久中文字幕乱码免费 | 成人伊人亚洲人综合网站222 |