Test_v1 → Test_v2)ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
ClassReader cr = new ClassReader(new FileInputStream(cs.getFile()));
ClassModifier cm = new ClassModifier(cw); // 修改類型為接口,清空方法體
cr.accept(cm, 0);
byte[] code = cw.toByteArray();
defineClass(className, code, 0, code.length); // 定義為接口
ClassReader cr = new ClassReader(new FileInputStream(classSource.getFile()));
EnhancedModifier em = new EnhancedModifier(cw, origName, enhancedName); // 改類名
ExtendModifier exm = new ExtendModifier(em, origName, enhancedName); // 實現原接口
cr.accept(exm, 0);
byte[] code = cw.toByteArray();
defineClass(enhancedName, code, 0, code.length);
EnhancedModifier:修改類名(Test → Test_v1)ExtendModifier:修改父類為原接口(implements Test)ClassReader → ClassVisitor 鏈 → ClassWriterClassLoader 內置定時器掃描目標 .class 文件修改時間,變更觸發重新加載生成新版本派生類。
// 原始
Greeter p = new Greeter();
// 修改後
IGreeter p = (IGreeter) MyClassLoader.getInstance().findClass("com.example.Greeter").newInstance();
ASM 訪問 NEW 指令時替換為:
mv.visitMethodInsn(INVOKESTATIC, CLASSLOAD_TYPE, "getInstance", "()L"+CLASSLOAD_TYPE+";");
mv.visitLdcInsn(type.replace("/", "."));
mv.visitMethodInsn(INVOKEVIRTUAL, CLASSLOAD_TYPE, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "newInstance", "()Ljava/lang/Object;");
mv.visitTypeInsn(CHECKCAST, compileType);
Class.forName()、ClassLoader.findClass() 行為public class ReloadAgent {
public static void premain(String agentArgs, Instrumentation inst) {
GeneralTransformer trans = new GeneralTransformer();
inst.addTransformer(trans);
}
}
MANIFEST.MF:
Premain-Class: com.example.ReloadAgent
Can-Redefine-Classes: true
啟動參數:-javaagent:reload-agent.jar=projectPath 
public byte[] transform(ClassLoader loader, String className, Class> classBeingRedefined,
ProtectionDomain pd, byte[] classfileBuffer) {
className = className.replace("/", ".");
if (className.equals("com.example.Test")) {
MyClassLoader cl = MyClassLoader.getInstance();
cl.defineReference(className, "com.example.Greeter");
return cl.getByteCode(className);
} else if (className.equals("com.example.Greeter")) {
MyClassLoader cl = MyClassLoader.getInstance();
cl.redefineClass(className);
return cl.getByteCode(className);
}
return null; // 不轉換
}

熱部署難點在於**類生命周期管理**與**存量對象狀態遷移**。期待未來 JDK 重新設計類生命周期,支援運行時完整類更新,讓 Java 應用更新更友好,告別頻繁重啟。