自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

整理Java中的ClassLoader核心知識點

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

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

[[350691]]

JDK 和 JRE 的作用

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

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文件等。

  1. //執(zhí)行 
  2. System.out.println(System.getProperty("sun.boot.class.path")); 
  3. //輸出結果 
  4. D:\Program Files\Java\jdk1.8.0_241\jre\lib\resources.jar; 
  5. D:\Program Files\Java\jdk1.8.0_241\jre\lib\rt.jar; 
  6. D:\Program Files\Java\jdk1.8.0_241\jre\lib\sunrsasign.jar; 
  7. D:\Program Files\Java\jdk1.8.0_241\jre\lib\jsse.jar; 
  8. D:\Program Files\Java\jdk1.8.0_241\jre\lib\jce.jar; 
  9. D:\Program Files\Java\jdk1.8.0_241\jre\lib\charsets.jar; 
  10. D:\Program Files\Java\jdk1.8.0_241\jre\lib\jfr.jar; 
  11. D:\Program Files\Java\jdk1.8.0_241\jre\classes 

(2) Extention ClassLoader

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

  1. //執(zhí)行 
  2. System.out.println(System.getProperty("java.ext.dirs")); 
  3. //輸出 
  4. D:\Program Files\Java\jdk1.8.0_241\jre\lib\ext;C:\Windows\Sun\Java\lib\ext 

(3) Appclass Loader

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

類加載器的執(zhí)行順序

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

  1. public Launcher() { 
  2.     Launcher.ExtClassLoader var1; 
  3.     try { 
  4.         //初始化擴展類加載器,構造函數(shù)沒有入?yún)?,無法獲取啟動類加載器 
  5.         var1 = Launcher.ExtClassLoader.getExtClassLoader(); 
  6.     } catch (IOException var10) { 
  7.         throw new InternalError("Could not create extension class loader", var10); 
  8.     } 
  9.  
  10.     try { 
  11.         //初始化應用類加載器,入?yún)閿U展類加載器 
  12.         this.loader = Launcher.AppClassLoader.getAppClassLoader(var1); 
  13.     } catch (IOException var9) { 
  14.         throw new InternalError("Could not create application class loader", var9); 
  15.     } 
  16.  
  17.     // 設置上下文類加載器 
  18.     Thread.currentThread().setContextClassLoader(this.loader); 
  19.      
  20.    //... 

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

父加載器概念

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

  1. System.out.println("ClassLoader is:"+cl.toString()); 
  2. 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都是由它加載。然后呢,我們前面已經(jīng)分析了,JVM初始化sun.misc.Launcher并創(chuàng)建Extension ClassLoader和AppClassLoader實例。并將ExtClassLoader設置為AppClassLoader的父加載器。Bootstrap沒有父加載器,但是它卻可以作用一個ClassLoader的父加載器。

雙親委派

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

整理Java中的ClassLoader核心知識點

整理Java中的ClassLoader核心知識點

時序圖

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

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

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

自定義類加載器

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

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

  1. public class ClassLoaderTest extends ClassLoader { 
  2.  
  3.     private String classPath; 
  4.  
  5.     public ClassLoaderTest(String classPath) { 
  6.         this.classPath = classPath; 
  7.     } 
  8.  
  9.     /** 
  10.      * 編寫findClass方法的邏輯 
  11.      * 
  12.      * @param name 
  13.      * @return 
  14.      * @throws ClassNotFoundException 
  15.      */ 
  16.     @Override 
  17.     protected Class<?> findClass(String name) throws ClassNotFoundException { 
  18.         // 獲取類的class文件字節(jié)數(shù)組 
  19.         byte[] classData = getClassData(name); 
  20.         if (classData == null) { 
  21.             throw new ClassNotFoundException(); 
  22.         } else { 
  23.             // 生成class對象 
  24.             return defineClass(name, classData, 0, classData.length); 
  25.         } 
  26.     } 
  27.  
  28.     /** 
  29.      * 編寫獲取class文件并轉換為字節(jié)碼流的邏輯 
  30.      * 
  31.      * @param className 
  32.      * @return 
  33.      */ 
  34.     private byte[] getClassData(String className) { 
  35.         // 讀取類文件的字節(jié) 
  36.         String path = classNameToPath(className); 
  37.         try { 
  38.             InputStream is = new FileInputStream(path); 
  39.             ByteArrayOutputStream stream = new ByteArrayOutputStream(); 
  40.             byte[] buffer = new byte[2048]; 
  41.             int num = 0
  42.             // 讀取類文件的字節(jié)碼 
  43.             while ((num = is.read(buffer)) != -1) { 
  44.                 stream.write(buffer, 0, num); 
  45.             } 
  46.             return stream.toByteArray(); 
  47.         } catch (IOException e) { 
  48.             e.printStackTrace(); 
  49.         } 
  50.         return null; 
  51.     } 
  52.  
  53.     /** 
  54.      * 類文件的完全路徑 
  55.      * 
  56.      * @param className 
  57.      * @return 
  58.      */ 
  59.     private String classNameToPath(String className) { 
  60.         return classPath + File.separatorChar 
  61.                 + className.replace('.', File.separatorChar) + ".class"; 
  62.     } 
  63.  
  64.     public static void main(String[] args) { 
  65.         String classPath = "/Users/zzs/my/article/projects/java-stream/src/main/java/"
  66.         ClassLoaderTest loader = new ClassLoaderTest(classPath); 
  67.  
  68.         try { 
  69.             //加載指定的class文件 
  70.             Class<?> object1 = loader.loadClass("com.secbro2.classload.SubClass"); 
  71.             System.out.println(object1.newInstance().toString()); 
  72.         } catch (Exception e) { 
  73.             e.printStackTrace(); 
  74.         } 
  75.     } 

 

責任編輯:趙寧寧 來源: 今日頭條
相關推薦

2021-01-15 08:35:49

Zookeeper

2021-04-13 08:25:12

測試開發(fā)Java注解Spring

2020-10-26 10:40:31

Axios前端攔截器

2021-12-30 08:17:27

Springboot數(shù)據(jù)訪問DataSourceB

2025-01-07 14:10:46

SpringBoot開發(fā)Java

2024-11-04 09:00:00

Java開發(fā)

2021-01-06 13:52:19

zookeeper開源分布式

2020-05-19 14:40:08

Linux互聯(lián)網(wǎng)核心

2025-03-26 11:30:40

2024-04-23 14:25:16

Python備忘清單

2022-10-29 08:55:19

頁面react

2022-04-08 07:51:31

JavaJVM垃圾回收

2021-12-27 10:20:46

JavaNetty網(wǎng)絡

2024-06-04 14:07:00

2023-08-07 14:44:56

Socket文件描述符

2020-02-18 08:01:55

在家辦公Kakfa知識點大全

2017-03-07 13:03:34

AndroidView知識問答

2016-10-31 19:22:24

JavaScript語法

2021-04-29 10:01:30

JavaMathJava編程

2012-04-23 15:49:04

點贊
收藏

51CTO技術棧公眾號