JVM 学习三:类加载器
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                JVM 学习三:类加载器
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.                        
                                類加載器
1 類加載器的分類
JVM 支持兩種類型的類加載器:引導類加載器(Bootstrap ClassLoader)和自定義類加載器(User-Defined ClassLoader)
從概念上來講,自定義類加載器一般指的是程序中由開發人員自定義的一類加載器,但是 Java 虛擬機規范卻沒有這么定義,而是將所有派生于抽象類 ClassLoader 的類加載器都劃分為自定義類加載器
無論類加載器的類型如何劃分,在程序中我們最常見的類加載器始終只有 3 個,如下所示:
 
 關于 ClassLoader:
 
 測試代碼:ClassLoaderTest.java
2 虛擬機自帶的加載器
2.1 啟動類加載器(引導類加載器,Bootstrap ClassLoader)
- 這個類加載器使用 C/C++ 語言實現的,嵌套在 JVM 內部
 - 它用來加載 Java 的核心庫(JAVA_HOME/jre/lib/rt.jar、resources.jar 或 sun.boot.class.path 路徑下的內容),用于提供 JVM 自身需要的類
 - 并不繼承自 java.lang.ClassLoader,沒有父加載器
 - 加載擴展類和應用程序類加載器,并指定為它們的父類加載器
 - 出于安全考慮,Bootstrap ClassLoader 啟動類加載器只加載包名為 java、javax、sun 開頭的類
 
測試類 ClassLoaderTest2.java
public class ClassLoaderTest2 {public static void main(String[] args) {System.out.println("======== 啟動類加載器 ========");// 獲取 BootstrapClassLoader 能夠加載的 API 路徑URL[] urLs = Launcher.getBootstrapClassPath().getURLs();for (URL urL : urLs) {System.out.println(urL.toExternalForm());}// 驗證 jsse.jar 包下 Provider 類的類加載器為 Bootstrap ClassLoaderSystem.out.println(Provider.class.getClassLoader()); // null} }Provider 類由引導類加載器加載:
 
 輸出結果:
 
2.2 擴展類加載器(Extension ClassLoader)
- Java 語言編寫的,由 sun.misc.Launcher$ExtClassLoader 實現
 - 派生于 ClassLoader 類
 - 父類加載器為啟動類加載器
 - 從 java.ext.dirs 系統屬性所指定的目錄中加載類庫,或從 JDK 的安裝目錄的 jre/lib/ext 子目錄(擴展目錄)下加載類庫。如果用戶創建的 JAR 放在此目錄下,也會自動由擴展類加載器加載
 
測試類 ClassLoaderTest3.class
public class ClassLoaderTest3 {public static void main(String[] args) {System.out.println("======= 擴展類加載器 =======");String extDirs = System.getProperty("java.ext.dirs");for (String path : extDirs.split(";")) {System.out.println(path);}// 驗證 CurveDB 是由 ExtClassLoader 加載器所加載的System.out.println(CurveDB.class.getClassLoader()); // sun.misc.Launcher$ExtClassLoader@7ea987ac} }CurveDB 類是由 ExtClassLoader 加載器所加載的
 
 輸出結果:
 
2.3 應用程序類加載器(系統類加載器,AppClassLoader)
- Java 語言編寫,由 sun.misc.Launcher$AppClassLoader 實現
 - 派生于 ClassLoader 類
 - 父類加載器為擴展類加載器
 - 它負責加載環境變量 classpath 或系統屬性 java.class.path 指定路徑下的類庫
 - 應用程序類加載器程序中默認的類加載器,一般來說,Java 應用的類都是由它來完成加載
 - 通過 ClassLoader#getSystemClassLoader() 方法可以獲取到該類加載器
 
測試類 ClassLoaderTest.java
public class ClassLoaderTest4 {public static void main(String[] args) {// 獲取用戶自定義類的類加載器System.out.println(ClassLoaderTest4.class.getClassLoader());/*** 輸出結果為:sun.misc.Launcher$AppClassLoader@18b4aac2*/} }3 用戶自定義類加載器
在 Java 的日常應用程序開發中,類的加載幾乎都是同上述 3 種類加載器相互配合完成的,但是在必要的時候,我們也可以自定義類加載器,來定制類的加載方式。
3.1 為什么要自定義類加載器
- 隔離加載類
 - 修改類加載的方式
 - 擴展加載源
 - 防止源碼泄漏
 
3.2 自定義類加載器實現步驟
簡單的類加載器實現 CustomClassLoader.java
public class CustomClassLoader extends ClassLoader {@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {try {byte[] result = getClassFromCustomPath(name);if (result == null) {throw new FileNotFoundException();} else {return defineClass(name, result, 0, result.length);}} catch (FileNotFoundException e) {e.printStackTrace();}throw new ClassNotFoundException(name);}private byte[] getClassFromCustomPath(String name) {// 從自定義路徑中加載指定類:細節略// 如果指定路徑的字節碼文件進行了加密,則需要在此方法中進行解密操作return null;}public static void main(String[] args) {CustomClassLoader customClassLoader = new CustomClassLoader();try {Class<?> clazz = Class.forName("One", true, customClassLoader);Object obj = clazz.newInstance();System.out.println(obj.getClass().getClassLoader());} catch (Exception e) {e.printStackTrace();}} }4 關于 ClassLoader
ClassLoader 類是一個抽象類,其后所有的類加載器都繼承自 ClassLoader (不包括啟動類加載器)
4.1 方法介紹
| getParent() | 返回該類加載器的超類加載器 | 
| loadClass(String name) | 加載名稱為 name 的類,返回結果為 java.lang.Class 類的實例 | 
| findClass(String name) | 查找名為 name 的類,返回結果為 java.lang.Class 類的實例 | 
| findLoadedClass(String name) | 查找名為 name 的已經被加載過的類,返回結果為 java.lang.Class 的類的實例 | 
| defineClass(String name, byte[] b, int off, int len) | 把字節數組 b 中的內容轉換為一個 Java 類,返回結果為 java.lang.Class 類的實例 | 
| resolveClass(Class<?> c) | 連接指定的一個 Java 類 | 
4.2 獲取 ClassLoader 的途徑
- 獲取當前類的 ClassLoader: clazz.getClassLoader()
 - 獲取當前線程上下文的 ClassLoader: Thread.currentThread().getContextClassLoader()
 - 獲取系統的 ClassLoader: ClassLoader.getSystemClassLoader()
 - 獲取調用都的 ClassLoader: DriverManager.getCallerClassLoader()
 
總結
以上是生活随笔為你收集整理的JVM 学习三:类加载器的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: java的求和函数_Java Strea
 - 下一篇: maven pom java版本_Mav