首页 > 编程语言 >JAVA-Agent探针打印方法执行的返回值

JAVA-Agent探针打印方法执行的返回值

时间:2024-05-02 22:11:07浏览次数:29  
标签:java classfileBuffer jar 打印 探针 Agent org import JAVA

 

1、创建一个maven项目,不要用springboot的

 

引入依赖

<dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.12.0</version>
        </dependency>

        <dependency>
            <groupId>org.javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.29.0-GA</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.83</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.3.24</version>
        </dependency>

其中 javassist这个依赖必须的 其他是代码逻辑用到的 根据自己需要来

 

设置打包插件

<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <!--将所有依赖都打入同一个jar包中-->
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <!--指定java agent相关配置文件-->
                    <archive>
                        <manifestFile>src/main/resources/MANIFEST.MF</manifestFile>
                    </archive>
                </configuration>
            </plugin>

 

 

编写主类代码

JavaAgent.java

import java.lang.instrument.Instrumentation;

/**
 * 拦截打印方法的返回值
 */
public class JavaAgent {

    public static void premain(String agentArgs, Instrumentation inst) {
        inst.addTransformer(new ClassPreProcessorAgentAdapter(), true);
    }

}

 

ClassPreProcessorAgentAdapter.java

import javassist.*;
import org.apache.commons.lang3.StringUtils;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;

/**
 * 打印方法返回值 具体逻辑
 */
public class ClassPreProcessorAgentAdapter implements ClassFileTransformer {


    @Override
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {


        //是我们自己写的类才打印
        if (StringUtils.isBlank(className)) {
            return classfileBuffer;
        }

        //将类名路径 / 换成 .
        String classPkgName = className.replace('/', '.');

        //如果不是我们写的类 直接返回 这里自定义逻辑
        if (!classPkgName.contains("IndexController")) {
            return classfileBuffer;
        }
        final ClassPool pool = ClassPool.getDefault();

        try {
            CtClass ctClass = pool.makeClass(new java.io.ByteArrayInputStream(classfileBuffer));
            //匹配类的路径是我们要的才打印
            if (ctClass.getName().replace('/', '.').startsWith("com.example.demotest")) {
                for (CtMethod method : ctClass.getDeclaredMethods()) {
                    if (method.hasAnnotation(org.springframework.web.bind.annotation.RequestMapping.class)) {
                        // 这句话最重要 打印返回值的内容
                        method.insertAfter("System.out.println(\"Controller Method Returned: \" + $_);");
                    }
                }
                return ctClass.toBytecode();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println("premain load Class:" + className);
        return classfileBuffer;
    }


}

 

然后resource下放文件

MANIFEST.MF

Manifest-Version: 1.0
Specification-Title: Log Agent
Specification-Version: 0.0.1
Specification-Vendor: LogAgent
Implementation-Title: log.agent
Implementation-Version: 0.0.1
Implementation-Vendor: LogAgent
Premain-Class: com.demo.agent.JavaAgent
Can-Redefine-Classes: true
Can-Retransform-Classes: true

 

  Premain-Class:这个就是我们写的premain的类的全路径 我这里是JavaAgent的类路径 根据自己的来

 最后一行要空一行 ,这个不能少 

 

 

最后打包,会生成一个  jar-with-dependencies.jar结尾的jar包,然后我们通过启动的时候命令引用进去即可

-javaagent:D:\jar包路径\agent-jar-with-dependencies.jar

 

IDEA的话是在那个启动类的 VM options里面设置

如果要调试代码的话 要把启动的项目和我们agent的项目放在一个工程底下,这样idea就能自动断点到

 

标签:java,classfileBuffer,jar,打印,探针,Agent,org,import,JAVA
From: https://www.cnblogs.com/pxblog/p/18170645

相关文章

  • day30-JavaScript(2)
    1、BOM对象BOM:Broswerobjectmodel,即浏览器提供我们开发者在javascript用于操作浏览器的对象。1.1、window对象窗口方法//BOMBrowserobjectmodel浏览器对象模型//js中最大的一个对象.整个浏览器窗口出现的所有东西都是window对象的内容.console.log(window);......
  • 新人小白第一天学Java
    我对计算机知识学习是比较感兴趣的,但是说实在话计算机语言学习我还是第一次接触,也是0基础学习。虽然不知道会学成什么样子,但我会不断坚持的去学习,希望会收到好的效果。我从事文员的这个工作岗位已经十多年了,虽然平时对计算机办公软件的使用和一般维护有所应用,但对于在计算机语言方......
  • typescript仅仅是为了给javascript增加类型而对java的一个仿制吗
    如果是这样,我不直接学习java或者c#就好了吗?(不考虑前端编程这个因素)或者换句话说,typescript跟java在语法语义有什么不同吗?能给编程带来什么帮助吗?带着这个疑问,翻了一下现有的资料,找到typescript官网的一段解释,觉得有点意思,翻出来,供大家参考。https://www.typescriptlang.org/doc......
  • Java(4)-十大排序算法
    更好的总结:RUNOOB.COM十大经典排序算法冒泡排序冒泡排序的基本思想是比较数组中相邻的两个元素,根据比较结果交换它们的位置,让较大的元素排到数组末尾。遍历过程:首轮遍历:从数组的第一个元素开始,比较相邻的两个元素,如果前一个元素大于后一个元素,则交换它们的位置,从而第一遍遍......
  • Java线程池核心线程用尽后为何优先排队而不是继续创建线程直至最大线程数?
    前阵子在v2ex上看到这篇帖子讨论这个问题,有意思的是这个如此基础的问题在Javaer的世界里并没有广泛的共识,下面的回答也是七嘴八舌的,刚好在《JavaPerformace》上看到对这个问题的解释,尝试总结一下。原因书中对线程池的解释基于以下几点前提:如果CPU已经跑满,增加线程并不能提高......
  • 一份透心凉的北森java冷面(面经)
    1.对于分布式的理解2.几台机器合作怎么保证高可用3.es打了几个节点4.为什么es快5.es的build和body的区别6.es想进行时间范围搜索,用到什么命令和接口7.es的索引有哪些8.redis为什么搜索快9.在什么地方使用了redis10.将数据直接放到本地内存里更快,为什么用redis11.分布式......
  • java命名规范
    1、java文件名规范a、一个文件中最多只能有一个public类且文件名必须和public类名一致b、文件中可以有多个类,若无public修饰的类,此文件名可以是任意名2、java类与成员命名规范a、类名规范-类名首字母必须大写,使用驼峰命名法b、类修饰符(写在类前边,只有两种)-public-defau......
  • 05.Java 方法详解
    1.方法的定义及调用设计方法的原则:一个方法只完成一个功能,有利于后期的扩展方法的定义:修饰符(可选)返回值类型方法名(参数类型参数名(可选)){方法体return返回值;}2.方法重载重载:就是在一个类中,有相同的函数名称,但形参不通的函数方法的重载规则:方法名称必......
  • Java注解和反射
    元注解:负责注解其他的注解,Java定义了4个标准的meta-annotation类型@Target:用于描述注解的适用范围@Retention:表示需要再什么级别保存该注解信息,用于描述注解的生命周期(source<class<runtime)@Document:该注解江北包含在javadoc中@Inherited:说明子类可以继承父类中的注解自......
  • day29-JavaScript(1)
    1、JavaScript的历史1.1、JavaScript的历史JavaScript因为互联网而生,紧随着浏览器的出现而问世。回顾它的历史,就要从浏览器的历史讲起。1990年底,欧洲核能研究组织(CERN)科学家TimBerners-Lee,在全世界最大的电脑网络——互联网的基础上,发明了万维网(WorldWideWeb),从此可以在网......