專案流程:接收程式碼字串 → JavaCompiler 編譯成 A.class → 反射呼叫 main 方法執行。問題出現:更新 A.class 後,反射執行結果仍為首次結果。
| 載入器 | 類型 | 負責載入範圍 |
|---|---|---|
| Bootstrap ClassLoader | C/C++ 實作,內建 JVM 核心 | <JAVA_HOME>/lib 核心類別庫 |
| Extension ClassLoader | Java 類別 | <JAVA_HOME>/lib/ext 擴充套件 |
| Application ClassLoader | Java 類別 | Classpath 指定路徑(專案 bin 目錄) |
ClassLoader.loadClass() 核心邏輯:
findLoadedClass),是則直接返回parent.loadClass)findClass 載入因為 A.class 放在 Classpath 下,AppClassLoader 發現已載入同名類別,直接返回快取,導致無法重載更新後的類別。
loadClass 強制重載@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
byte[] data = loadClassData(name);
return defineClass(name, data, 0, data.length);
}
錯誤原因:嘗試載入 java.lang.Object 等核心類別時找不到路徑,破壞委派機制導致 FileNotFoundException。
findClass + 隔離類別路徑核心策略:
A.class 放在專案根目錄 myClass/(不在 Classpath)findClass 載入,實現熱更新public class MyClassLoader extends ClassLoader {
private String path = "myClass/";
private final String fileType = ".class";
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] data = loadClassData(name);
return defineClass(name, data, 0, data.length);
}
private byte[] loadClassData(String name) {
// 讀取 myClass/ 路徑下的 .class 檔案為位元組陣列
// ...
}
public static void main(String[] args) throws Exception {
for (int i = 0; i < 5; i++) {
MyClassLoader loader = new MyClassLoader();
loader.setPath("myClass/");
Class<?> clazz = loader.loadClass("Main");
// 每次 new ClassLoader 都能載入最新版本
}
}
}
ClassLoader 無卸載機制,需建立新實例載入新版本findClass,不破壞核心類別載入熱部署、外掛系統、動態編譯執行、多版本共存等需要運行時動態載入/更新類別的場景。