java agent测试

有包名再正确的目录执行

maven打agent jar包

org.apache.maven.plugins maven-jar-plugin com.agent.TestAgent com.agent.TestAgent true true

执行命令

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();
        }
    }
}
原文地址:https://www.cnblogs.com/albertXe/p/14756405.html