java探针示例

入口类

import com.yrx.agent.transformer.TraceTransformer;

import java.lang.instrument.Instrumentation;

/**
 * Created by r.x on 2019/10/22.
 */
public class TraceAgent {

    public static void premain(String option, Instrumentation ins) {
        ins.addTransformer(new TraceTransformer());
    }

    public static void main(String[] args) {

    }
}

字节码处理

import javassist.*;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;

/**
 * Created by r.x on 2019/10/22.
 */
public class TraceTransformer implements ClassFileTransformer {

    /** 遍历类名和方法名 start */
    /*@Override
    public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
        if (className.startsWith("com/yrx/datasourcemanager/manager/api")) {
            System.out.println("class name:{" + className + "}");
            // System.out.println(new String(classfileBuffer));
        } else {
            return null;
        }
        ClassReader reader = null;
        reader = new ClassReader(classfileBuffer);
        System.out.println("reader ----->" + reader);
        System.out.println("reader ----->" + reader.getClassName());
        ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_MAXS);
        System.out.println("writer ----->" + writer);
        ClassVisitor visitor = new ClassVisitor(Opcodes.ASM5, writer) {
            @Override
            public MethodVisitor visitMethod(int i, String name, String response, String responseSignature, String[] strings) {
                System.out.println("method name s:{" + name + "}");
                System.out.println("method name s1:{" + response + "}");
                System.out.println("method name s2:{" + responseSignature + "}");
                return super.visitMethod(i, name, response, responseSignature, strings);
            }

        };

        //忽略调试信息
        reader.accept(visitor, ClassReader.SKIP_DEBUG);
        return null;
    }*/
    /** 遍历类名和方法名 end */

    private byte[] addAop(String className, String methodName) {
        String currentMethodStr = "System.out.println(\"Thread.currentThread().getStackTrace()[1].getMethodName() = \" + Thread.currentThread().getStackTrace()[1].getMethodName());";
        ClassPool cp = ClassPool.getDefault();
        try {
            CtClass ctClass = cp.get(className);
            CtMethod declaredMethod = ctClass.getDeclaredMethod(methodName);
            declaredMethod.insertBefore(currentMethodStr);


            return ctClass.toBytecode();
        } catch (NotFoundException | CannotCompileException | IOException e) {
            System.out.println("==================== add aop error ! ====================");
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
        // todo 需要剔除接口
        if (className.startsWith("com/yrx/datasourcemanager/manager/") && !className.contains("$")) {
            ClassPool pool = new ClassPool(true);
            pool.appendClassPath(new LoaderClassPath(loader));
            try {
                CtClass cls = pool.makeClass(new ByteArrayInputStream(classfileBuffer));

                CtMethod[] methods = cls.getDeclaredMethods();
                for (CtMethod method : methods) {
                    //插入本地变量
                    method.addLocalVariable("startTime", CtClass.longType);
                    String codeStrBefore = "startTime=System.currentTimeMillis();";
                    StringBuilder stringBuilder = new StringBuilder();
                    stringBuilder.append("System.out.println(\"thread:[\"+Thread.currentThread().getName()+\"]")
                            .append("method:[" + className + "." + method.getName() + "] time cost [\"").append(" + (System.currentTimeMillis() - startTime) + \"]millisecond\");");

                    String codeStrAfter = stringBuilder.toString();
                    System.out.println(codeStrBefore);
                    System.out.println(codeStrAfter);
                    method.insertBefore(codeStrBefore);
                    method.insertAfter(codeStrAfter);
                }

                File file = new File("E:\\software\\intelliJ IDEA\\project\\manager\\agent\\src\\com\\yrx\\agent\\demo\\", cls.getSimpleName() + ".class");
                try (FileOutputStream fileOutputStream = new FileOutputStream(file)) {
                    fileOutputStream.write(cls.toBytecode());
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return cls.toBytecode();
            } catch (Exception e) {
                System.out.println(" ========= add aop error ========= className:" + className);
                e.printStackTrace();
            }
        }
        return null;
    }
}

执行

java -javaagent:./out/artifacts/agent_jar/agent.jar -jar ./target/manager-0.0.1-SNAPSHOT.jar

你可能感兴趣的:(java探针示例)