Java中的ClassLoader類加載器使用詳解
1. CLASSLOADER是什么
ClassLoader,類加載器。用于將CLASS文件動態(tài)加載到JVM中去,是所有類加載器的基類(Bootstrap ClassLoader不繼承自ClassLoader),所有繼承自抽象的ClassLoader的加載器,都會優(yōu)先判斷是否被父類加載器加載過,防止多次加載。
官網(wǎng)的JVM:https://docs.oracle.com/javase/specs/jvms/se8/jvms8.pdf
(1)定義:
把“類加載階段”中的「通過一個類的全限定名來獲取描述此類的二進(jìn)制字節(jié)流」這個動作放到JAVA虛擬機外部去實現(xiàn),以便讓應(yīng)用程序自己決定如何去獲取所需要的類。
實現(xiàn)這個動作的代碼模塊稱為「類加載器」。
(2)作用:
CLASSLOADER的作用就是將CLASS文件讀入內(nèi)存中,并為之生成對應(yīng)的java.lang.Class對象。
2. 三個默認(rèn)CLASSLOADER
①. BootStrap ClassLoader : 啟動類加載器,在JVM啟動時創(chuàng)建,用于加載JAVA核心類庫。它是JVM的一部分,主要加載JVM自身工作所需要的類。
②. Extension ClassLoader : 擴展類加載器,加載目錄%JRE_HOME%\lib\ext目錄下的JAR包和CLASS文件。
③. Application ClassLoader : 應(yīng)用程序類加載器,加載應(yīng)用程序CLASSPATH目錄下的所有JAR包和CLASS文件。

3. 默認(rèn)CLASSLOADER的關(guān)系
(1) 加載關(guān)系
①. ExtentionClassLoader的父加載器是BootstrapClassLoader。 ②. AppclassLoader的父加載器是ExtentionClassLoader。
(2) 繼承關(guān)系
①. ExtentionClassLoader對應(yīng)的是ExtClassLoader.java,是在sun.misc.Launcher類中作為一個內(nèi)部類的,父類是java.net.URLClassLoader;
②. AppclassLoader對應(yīng)的是AppClassLoader.java,也是在sun.misc.Launcher類中作為一個內(nèi)部類的,父類也是java.net.URLClassLoader;
③. BootstrapClassLoader是C++編寫的,沒有對應(yīng)的java類,所以也成不了父類。
(3) 檢查順序和加載順序
AppClassLoader和ExtClassLoader是Launcher的靜態(tài)內(nèi)部類,在程序啟動時JVM會創(chuàng)建Launcher對象,Launcher構(gòu)造器會同時會創(chuàng)建擴展類加載器和應(yīng)用類加載器。
①. 加載過程中會先檢查類是否被已加載,檢查順序是自底向上,從User ClassLoader到BootStrap ClassLoader逐層檢查,只要某個CLASSLOADER已加載過此類,就視為此類已被加載,保證此類在所有CLASSLOADER中只被加載一次;加載順序是自頂向下,從BootStrap ClassLoader到User ClassLoader逐層嘗試加載此類;
②. 在加載類時,每個類加載器都會將加載任務(wù)上交給其父類,如果其父類找不到,再由自己去加載;
③. Bootstrap Loader(啟動類加載器)是最頂級的類加載器了,其父加載器為NULL。
4. 自定義CLASSLOADER
如果我們自定義一個加載器,一般繼承自java.lang.ClassLoader類,或者繼承他的子類,比如:java.net.URLClassLoader,此時默認(rèn)的父加載器是AppClassLoader。具體步驟如下:
①. 編寫一個繼承自 java.lang.ClassLoader 或者 java.net.URLClassLoader 的類;
②. 重寫findClass()方法或者重寫loadClass()方法;
③. 在findClass()中使用defineClass()方法,這個方法是父類ClassLoader中的方法。
// 定義一個JAVA類
public class Hello {
public String say() {
System.out.println("HELLO WORLD!");
return "OK";
}
}
// 自定義類加載器
public class MyClassLoader extends ClassLoader {
private String path;
MyClassLoader(String path) {
this.path = path;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
File file = new File(this.path.concat(name).concat(".class"));
FileInputStream in = new FileInputStream(file);
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] bytes = new byte[1024];
int length = -1;
while ((length = in.read(bytes)) != -1) {
out.write(bytes, 0, length);
}
return defineClass(name, bytes, 0, bytes.length);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return super.findClass(name);
}
}
// 調(diào)用測試
public class T {
public static void main(String[] args) throws Exception {
String path = Hello.class.getClassLoader().getResource("org/apache/atlas/util/").getPath();
MyClassLoader my = new MyClassLoader(path);
// 注意需要帶上包路徑
Class<?> cls = my.loadClass("org.apache.atlas.util.Hello");
Object hello = cls.newInstance();
Method method = cls.getMethod("say", null);
method.invoke(hello);
}
}5. 使用自定義的CLASSLOADER是否可以熱加載CLASS?
①. JAVA目前沒有專門的API,來卸載JVM中已加載的類;
②. 要卸載JVM中的類,需要該類的對象都被回收,加載該類的ClassLoader也被回收,使用該類的線程結(jié)束等條件;
③. 但是,在JAVA中不同的ClassLoader實例可以加載同一個類,即使CLASS文件是同一個也可以被加載。但是同一個ClassLoader實例不能重復(fù)加載同一個類;
④. 綜上, 雖然可以熱加載CLASS,但是在不停服務(wù)的情況下熱替換CLASS不是很建議,雖然可以通過新建CLASSLOADER實例的方法來改變新加載的CLASS的內(nèi)容,但之前CLASSLOADER加載的類和對象并不會被修改,什么時候能被GC回收不可控。
到此這篇關(guān)于Java中的ClassLoader類加載器使用詳解的文章就介紹到這了,更多相關(guān)ClassLoader的使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java BeanPostProcessor與BeanFactoryPostProcessor基礎(chǔ)使用講解
這篇文章主要介紹了Java BeanPostProcessor與BeanFactoryPostProcessor基礎(chǔ)使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-11-11
基于Java實現(xiàn)Word轉(zhuǎn)EPUB的實現(xiàn)方案詳解
EPUB作為一種開放標(biāo)準(zhǔn)的電子書格式,已成為數(shù)字出版領(lǐng)域的主流選擇,本文將介紹一種基于?Java?的實現(xiàn)方案,供有類似需求的朋友參考,希望對大家有所幫助2026-04-04
SpringBoot啟動后自動執(zhí)行方法的各種方式對比
這篇文章主要為大家詳細(xì)介紹了SpringBoot啟動后自動執(zhí)行方法的各種方式和性能對比,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以參考一下2025-04-04
Mybatis-Plus中and()和or()的使用與原理詳解
最近發(fā)現(xiàn)MyBatisPlus還是挺好用的,下面這篇文章主要給大家介紹了關(guān)于Mybatis-Plus中and()和or()的使用與原理的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-09-09

