有包名再正确的目录执行
maven打agent jar包
执行命令
package com.agent;
import java.lang.instrument.Instrumentation;
public class TestAgent {
/**
* 执行一次
* @param args
* @param inst
*/
public static void premain(String args, Instrumentation inst){
System.out.println("before main: testAgent start!" + args);
inst.addTransformer(new TestTransformer());
}
public static void premain(String args) {
}
}
package com.agent;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
public class TestTransformer implements ClassFileTransformer {
/**
* 每个类加载都会执行
* @param loader
* @param className
* @param classBeingRedefined
* @param protectionDomain
* @param classfileBuffer
* @return
* @throws IllegalClassFormatException
*/
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
// 这里没有修改字节码信息 可以用asm javaassist修改
System.out.println("do not edit code!"+className);
return classfileBuffer;
}
}
public class AliTransformerByJavassist implements ClassFileTransformer {
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
System.out.println("正在重写类" + className);
try {
ClassPool classPool = ClassPool.getDefault();
CtClass ctClass = classPool.get("com.aliproject.bytecodeenforce.base.Base");
CtMethod ctMethodNoneParams = ctClass.getDeclaredMethod("processJavassist");
ctMethodNoneParams.insertBefore("{System.out.println("Javassist Start");}");
ctMethodNoneParams.insertAt(1, true,"{System.out.println("Insert Line");}");
ctMethodNoneParams.insertAfter("{System.out.println("Javassist End");}");
return ctClass.toBytecode();
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
Attach机制
对于一个运行中的JVM,要想修改它已经加载的类字节码,就必须和它进行交互。这就必然涉及到JVM进程之间的交互,所幸的是Java提供了JVM之间的通信机制--Attach机制。在已知要链接的JVM的PID后,可以直接通过attach(pid)函数和目标JVM建立通信,如代码中的VirtualMachine.attach(virtualMachineDescriptor.id())。
public class AliAttache {
private static final String AGENT_JAR = "/Users/baiyongjian/aliproject/bytecodeenforce/agent/target/agent-1.0-SNAPSHOT.jar";
private static final String TARGET_VIRTUAL_MACHINE = "com.aliproject.bytecodeenforce.base";
public static void main(String[] args) {
try {
List<VirtualMachineDescriptor> virtualMachineDescriptors = VirtualMachine.list();
for(VirtualMachineDescriptor virtualMachineDescriptor : virtualMachineDescriptors){
String displayName = virtualMachineDescriptor.displayName();
if(displayName.startsWith(TARGET_VIRTUAL_MACHINE)){
VirtualMachine virtualMachine = VirtualMachine.attach(virtualMachineDescriptor.id());
virtualMachine.loadAgent(AGENT_JAR);
virtualMachine.detach();
}
}
}catch (Exception e){
e.printStackTrace();
}
}
}