JDK 1.2+ 採雙親委派模型載入類別:ClassLoader 尋找不到類別時委派父載入器,根載入器為系統載入器(預設從本地檔案系統載入)。探討 JVM 內部運作機制。
loadClass(String, boolean):入口點,JDK 1.2+ 預設調用 findClassdefineClass(String, byte[], int, int):核心,將位元組碼解析為運行時資料結構、驗證有效性,final 不可覆寫findSystemClass:從本地檔案系統載入findClass:自訂載入邏輯入口,預設實作拋出 ClassNotFoundExceptiongetSystemClassLoader、getParent:存取系統/父載入器resolveClass:解析類別(視 loadClass 的 resolve 參數)findLoadedClass:快取檢查,避免重複載入findLoadedClass 檢查快取loadClass(父為 null 則用系統載入器)findClass 查找類別resolveClassClassNotFoundExceptionClass 物件CompilingClassLoader:檢查 .java 檔是否比 .class 新,若是則呼叫 javac 編譯,再以 defineClass 載入。測試類別 TestRun 使用反射呼叫載入類別的 main 方法。
// 核心 loadClass 邏輯
Class clas = findLoadedClass(name);
String fileStub = name.replace('.', '/');
File javaFile = new File(fileStub + ".java");
File classFile = new File(fileStub + ".class");
if (javaFile.exists() && (!classFile.exists() || javaFile.lastModified() > classFile.lastModified())) {
compile(javaFile); // 呼叫 javac
}
byte[] raw = getBytes(classFile.getPath());
clas = defineClass(name, raw, 0, raw.length);
if (clas == null) clas = findSystemClass(name);
if (resolve && clas != null) resolveClass(clas);
編譯 CompilingClassLoader、TestRun,撰寫簡單 Hello.java,執行 java TestRun Hello 參數,輸出 Hello,參數,驗證自訂載入器運作。