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) {

    }
}

字節(jié)碼處理

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);
            }

        };

        //忽略調(diào)試信息
        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;
    }
}

執(zhí)行

java -javaagent:./out/artifacts/agent_jar/agent.jar -jar ./target/manager-0.0.1-SNAPSHOT.jar
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 第6章類文件結(jié)構(gòu) 6.1 概述 6.2 無(wú)關(guān)性基石 6.3 Class類文件的結(jié)構(gòu) java虛擬機(jī)不和包括java...
    kennethan閱讀 1,068評(píng)論 0 2
  • 一:java概述:1,JDK:Java Development Kit,java的開(kāi)發(fā)和運(yùn)行環(huán)境,java的開(kāi)發(fā)工...
    ZaneInTheSun閱讀 2,800評(píng)論 0 11
  • 第二部分 自動(dòng)內(nèi)存管理機(jī)制 第二章 java內(nèi)存異常與內(nèi)存溢出異常 運(yùn)行數(shù)據(jù)區(qū)域 程序計(jì)數(shù)器:當(dāng)前線程所執(zhí)行的字節(jié)...
    小明oh閱讀 1,275評(píng)論 0 2
  • 原文:Java探針-Java Agent技術(shù)利用JAVA探針?lè)治鰪?fù)雜代碼運(yùn)維實(shí)踐 總結(jié): 使用java代理來(lái)實(shí)現(xiàn)j...
    小小少年Boy閱讀 16,712評(píng)論 3 7
  • 《深入理解Java虛擬機(jī)》筆記_第一遍 先取看完這本書(JVM)后必須掌握的部分。 第一部分 走近 Java 從傳...
    xiaogmail閱讀 5,459評(píng)論 1 34

友情鏈接更多精彩內(nèi)容