文档章节

javaagent使用demo详解

xiaomin0322
 xiaomin0322
发布于 09/22 22:18
字数 1075
阅读 27
收藏 1

javaagent又称java探针,结合javassist或asm等框架对字节码文件进行操作,从而更优雅的实现“AOP”等功能,减少对原代码的侵入性等。从而我们可以借此来实现微服务等的全链路追踪以及项目环境隔离等功能。好了话不多说,直接写示例吧:
示例分为两个项目:1、agent项目:agentdemo,2、被代理项目agentclient
我们要做的是:用agent项目来修改被代理项目中指定的hello方法,在原有的基础上添加一行代码输出一句话,又比如说我们要拦截redis发送命令的方法,从而获取相关的信息等。
一、先来写agent项目:
1、新建一个简单的maven项目
2、编辑pom文件,引入javassist依赖,以及指定premainClass(在main方法执行前会被执行的方法)生成MANIFEST.MF文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zxing</groupId>
    <artifactId>agentdemo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.11.0.GA</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>utf-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.0.0</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer
                                        implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <manifestEntries>
                                        <!--修改为你自己的类名全路径-->
                                        <Premain-Class>com.zxing.agent.App</Premain-Class>
                                    </manifestEntries>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
3、创建FirstAgent类,实现ClassFileTransformer 接口,修改字节码

package com.zxing.agent;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;

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

/**
 * Created by ZXing at 2018/12/19
 * QQ:1490570560
 */
public class FirstAgent implements ClassFileTransformer {
    public final String injectedClassName = "com.zxing.agentclient.App";
    public final String methodName = "hello";

    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
        className = className.replace("/", ".");
//        System.out.println(className);
        if (className.equals(injectedClassName)) {
            CtClass ctclass = null;
            try {
                ctclass = ClassPool.getDefault().get(className);// 使用全称,用于取得字节码类<使用javassist>
                CtMethod ctmethod = ctclass.getDeclaredMethod(methodName);// 得到这方法实例
                ctmethod.insertBefore("System.out.println(11111111);");//插入一行代码
                return ctclass.toBytecode();
            } catch (Exception e) {
                System.out.println(e.getMessage());
                e.printStackTrace();
            }
        }
        return null;
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
4、创建App类,重写javaagent的premain方法

package com.zxing.agent;

import java.lang.instrument.Instrumentation;

/**
 * Created by ZXing at 2018/12/19
 * QQ:1490570560
 */
public class App {
    public static void premain(String agentOps, Instrumentation inst) {
        System.out.println("=========premain方法执行========");
        System.out.println(agentOps);//-javaagent:xxxagent.jar=后携带的参数
        // 添加Transformer
        inst.addTransformer(new FirstAgent());
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
二、接下来我们写被代理项目,再新建一个项目agentclient
1、修改pom文件,指定main类,生成MANIFEST.MF文件(打开jar包可查看)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zxing</groupId>
    <artifactId>agentclient</artifactId>
    <version>1.0-SNAPSHOT</version>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.0.0</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer
                                        implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                     <!--修改为你自己的类全路径-->
                                    <mainClass>com.zxing.agentclient.App</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
这个项目很简单,只有一个App类,main方法,以及我们要拦截的hello方法:
创建App类:

package com.zxing.agentclient;

/**
 * Created by ZXing at 2018/12/19
 * QQ:1490570560
 */
public class App {
    public static void main(String[] args) {
        hello();
    }

    public static void hello() {
        System.out.println("this is agent-client output");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
三、两个项目分别使用maven打包
打包:mvn clean package
将打包后的两个jar包以及javassist jar包拷贝至同一个文件夹下
四、命令启动被代理项目

java -javaagent:agentdemo-1.0-SNAPSHOT.jar=abc -jar agentclient-1.0-SNAPSHOT.jar
1
输出:

=========premain方法执行========
abc
11111111
this is agent-client output
————————————————
 

本文转载自:https://blog.csdn.net/qq_35119422/article/details/85096592

xiaomin0322
粉丝 146
博文 3935
码字总数 199458
作品 0
上海
架构师
私信 提问
只用五分钟为系统实现基于JMX的监控

@MBean(objectName="jsmx:type=Demo")class ManagableServer { } ManagableServer mBean = new ManagableServer();new MBeanRegistration(mBean).register(); java -javaagent:/path/to/jolo......

zhongl
2011/08/01
9.7K
3
java的premain

特性 在类的字节码载入JVM前会调用ClassFileTransformer的transform方法,从而实现修改原类方法的功能。 原理 JVMTI(Java Virtual Machine Tool Interface)是一套本地编程接口集合,它提供...

go4it
2016/10/15
44
0
支持缓存线程池的ThreadLocal--Transmittable ThreadLocal(TTL)

主页 功能 需求场景 User Guide 2.1 修饰Runnable和Callable 2.2 修饰线程池 2.3 使用Java Agent来修饰JDK线程池实现类 整个过程的完整时序图 Java Agent的使用方式在什么情况下TTL会失效 ...

oldratlee
2013/12/05
4.3K
0
字节码实战--手写一个btrace

简易的btrace需求 偶现的方法执行慢,我们是可以用jstack捕捉到的,但是慢到什么地步却是不一定知道的,现在就需要在不重启应用的情况下,获取方法执行的时间。 需求特点 应用不重启 获取方法...

xpbob
2018/07/05
2.1K
3
Tomcat热部署的三种方式

热部署是指在你修改项目BUG的时候对JSP或JAVA类进行了修改在不重启WEB服务器前提下能让修改生效。但是对配置文件的修改除外! 1、直接把项目web文件夹放在webapps里。 2、在tomcatconfserver....

xiaml
2016/12/07
958
0

没有更多内容

加载失败,请刷新页面

加载更多

【1015】LNMP架构二

【1015】LNMP架构二 三、PHP安装 PHP安装和LAMP安装PHP方法有差别,需要开启php-fpm服务 1、下载PHP7至/usr/local/src/ 切换目录:cd /usr/local/src 2、解压缩 tar -jxvf php-7.3.0.tar.gz...

飞翔的竹蜻蜓
29分钟前
3
0
浅谈Visitor访问者模式

一、前言 什么叫访问,如果大家学过数据结构,对于这点就很清晰了,遍历就是访问的一般形式,单独读取一个元素进行相应的处理也叫作访问,读取到想要查看的内容+对其进行处理就叫作访问,那么...

青衣霓裳
48分钟前
6
0
JS内嵌多个页面,页面之间如何更快捷的查找相关联的页面

假设parent为P页面, P页面有两个子页面,分别为B页面和C页面; B页面和C页面分别内嵌一个iframe,分别为:D页面和E页面 现在通过B页面的内嵌页面D的方法refreshEpage(eUrl)来加载内嵌页面E的内容...

文文1
49分钟前
7
0
Hibernate 5 升级后 getProperties 错误

升级到 Hibernate 5 后,提示有错误: org.hibernate.engine.spi.SessionFactoryImplementor.getProperties()Ljava/util/Map; 完整的错误栈为: java.lang.NoSuchMethodError: org.hibernate......

honeymoose
50分钟前
6
0
mysql-connector-java升级到8.0后保存时间到数据库出现了时差

在一个新项目中用到了新版的mysql jdbc 驱动 <dependency>     <groupId>mysql</groupId>     <artifactId>mysql-connector-java</artifactId>     <version>8.0.18</version> ......

ValSong
53分钟前
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部