1)新建一个hello.jar模拟启动的应用程序
//HelloWorld.javapublic class HelloWorld { public static void main(String[] args) { System.out.println("start..."); hello h1 = new hello(); h1.hello(); // 产生中断,等待注入 Scanner sc = new Scanner(System.in); sc.nextInt(); hello h2 = new hello(); h2.hello(); System.out.println("ends..."); }}//hello.javapublic class hello { public void hello(){ System.out.println("hello world"); }}2)创建javaAgent.jar
//AgentDemo.javapackage com.test;import java.io.IOException;import java.lang.instrument.Instrumentation;import java.lang.instrument.UnmodifiableClassException;public class AgentDemo { public static void agentmain(String agentArgs, Instrumentation inst) throws IOException, UnmodifiableClassException { Class[] classes = inst.getAllLoadedClasses(); // 判断类是否已经加载 for (Class aClass : classes) { if (aClass.getName().equals(TransformerDemo.editClassName)) { // 添加 Transformer inst.addTransformer(new TransformerDemo(), true); // 触发 Transformer inst.retransformClasses(aClass); } } }}//TransformerDemo.javapackage com.test;import javassist.ClassClassPath;import javassist.ClassPool;import javassist.CtClass;import javassist.CtMethod;import java.lang.instrument.ClassFileTransformer;import java.lang.instrument.IllegalClassFormatException;import java.security.ProtectionDomain;public class TransformerDemo implements ClassFileTransformer { // 只需要修改这里就能修改别的函数 public static final String editClassName = "com.test.hello"; public static final String editClassName2 = editClassName.replace('.', 'http://www.likecs.com/'); public static final String editMethodName = "hello"; @Override public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { try { ClassPool cp = ClassPool.getDefault(); if (classBeingRedefined != null) { ClassClassPath ccp = new ClassClassPath(classBeingRedefined); cp.insertClassPath(ccp); } CtClass ctc = cp.get(editClassName); CtMethod method = ctc.getDeclaredMethod(editMethodName); String source = "{System.out.println(\"hello transformer\");}"; method.insertBefore(source); byte[] bytes = ctc.toBytecode(); ctc.detach(); return bytes; } catch (Exception e){ e.printStackTrace(); } return null; }}在MANIFEST.MF文件中加入
Manifest-Version: 1.0Agent-Class: com.test.AgentDemoCan-Redefine-Classes: trueCan-Retransform-Classes: true3)利用VirtualMachine注入
package com.test;import com.sun.tools.attach.AgentInitializationException;import com.sun.tools.attach.AgentLoadException;import com.sun.tools.attach.AttachNotSupportedException;import com.sun.tools.attach.VirtualMachine;import java.io.IOException;public class App { public static void main( String[] args ) { try { //VirtualMachine 来自tools.jar // VirtualMachine.attach("9444") 9444为线程PID VirtualMachine vm = VirtualMachine.attach("9444"); //指定要使用的Agent路径 vm.loadAgent("C:\\Users\\xxx\\Desktop\\javaAgent.jar"); } catch (AttachNotSupportedException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (AgentLoadException e) { e.printStackTrace(); } catch (AgentInitializationException e) { e.printStackTrace(); } }} 测试:运行hello.jar
使用VirtualMachine连接VM,进行注入后,第二次调用hello方法已经成功增加了一行hello transformer