package com.hotpatch; import java.lang.instrument.Instrumentation; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import org.apache.log4j.Logger; /** *Hot replacement * * @author ksfzhaohui * */ public class HotPatch { private final static Logger logger = Logger.getLogger(HotPatch.class); public static void premain(String agentArgs, Instrumentation inst) { Executors.newScheduledThreadPool(1).scheduleAtFixedRate( new HotPatchThread(inst), 5, 5, TimeUnit.SECONDS); logger.info("hotPatch starting..."); } }
package com.hotpatch; import java.io.File; import java.lang.instrument.ClassDefinition; import java.lang.instrument.Instrumentation; import java.util.List; import org.apache.log4j.Logger; /** *Hot Replace Thread * * @author ksfzhaohui * */ public class HotPatchThread implements Runnable { private final static Logger logger = Logger.getLogger(HotPatchThread.class); private static final String ROOT_PATH = "hotfiles"; private Instrumentation inst; public HotPatchThread(Instrumentation inst) { this.inst = inst; } public void run() { try { List<File> list = FileUtil.readfile(ROOT_PATH); if (list != null && list.size() > 0) { for (File file : list) { Class<?> clazz = Class.forName(getPackageName(file)); byte[] array = FileUtil.getBytesFromFile(file.getPath()); ClassDefinition def = new ClassDefinition(clazz, array); inst.redefineClasses(def); file.delete(); logger.info("hotpatch " + file.getPath() + " success"); } } } catch (Exception e) { logger.error("hotpatching error", e); } } /** *Get the package name+class name of the class * * @param file * @return */ private String getPackageName(File file) { String path = file.getPath(); int index = path.indexOf(ROOT_PATH); path = path.substring(index + ROOT_PATH.length() + 1); path = path.split("\\.")[0]; path = path.replaceAll("\\\\", "."); return path; } }
package agentTest; public class AgentTest { public static void main(String[] args) throws InterruptedException { TClass c = new TClass(); while (true) { System.out.println(c.getNumber()); Thread.sleep(1000); } } }
package agentTest; public class TClass { private int k = 10; public int getNumber() { return k + 4; } }
java -javaagent:hotpatch-0.0.1-SNAPSHOT.jar -cp test.jar agentTest.AgentTest