初识javaagent技术

硅谷探秘者 2097 0 1

JavaAgent 是运行在 main方法之前的拦截器,它内定的方法名叫 premain ,也就是说先执行 premain 方法然后再执行 main 方法。

Javaagent 只要作用在class被类加载器加载之前对其加载,并且可以修改类的字节码,插入我们需要添加的字节码。从而可以达到监控类的目的。

入门demo:

1.新建一个maven项目:

1545904208569053529.png

首先看带premain函数的类:

package club.jiajiajia.demo.agent;

import java.lang.instrument.Instrumentation;
public class MyAgent {
    /**
     * 该方法在main方法之前运行,与main方法运行在同一个JVM中
     * 并被同一个System ClassLoader装载
     * 被统一的安全策略(security policy)和上下文(context)管理
     */
    public static void premain(String agentOps, Instrumentation inst) {
        System.out.println("=========premain========");
        inst.addTransformer(new FirstAgent());
    }
}

在FirstAgent类中修改类的字节码:

package club.jiajiajia.demo.agent;
 
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
 
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
public class FirstAgent implements ClassFileTransformer {
    public final String injectedClassName = "agentTest.User";
    public final String methodName = "myName";
    
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
        className = className.replace("/", ".");
        if (className.equals(injectedClassName)) {
            CtClass ctclass = null;
            try {
                ctclass = ClassPool.getDefault().get(className);// 使用全称,用于取得字节码类<使用javassist>
                CtMethod ctmethod = ctclass.getDeclaredMethod(methodName);// 得到这方法实例
                ctmethod.insertBefore("System.out.println(\"I'm here to make trouble.\");");
                return ctclass.toBytecode();
            } catch (Exception e) {
                System.out.println(e.getMessage());
                e.printStackTrace();
            }
        }
        return null;
    }
}

pom文件:

<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>test</groupId>
  <artifactId>test3</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <dependencies>
	<dependency>
	    <groupId>org.javassist</groupId>
	    <artifactId>javassist</artifactId>
	    <version>3.23.1-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>club.jiajiajia.demo.agent.MyAgent</Premain-Class>
                                        <!--上面一定要填写MyAgent的全类名,也可以在MANIFEST.MF文件中配置-->
                                    </manifestEntries>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

此时我们执行:clean package 命令打包,然后得到我们需要的jar包,这个包会在后面用到->

image.png

2.新建一个测试项目:(当然也可以在上一个项目中测试)

image.png

User类:

package agentTest;

public class User {
	public User(String name) {
		super();
		this.name = name;
	}
	public User() {
		super();
		// TODO Auto-generated constructor stub
	}
	public String name;
	public void myName(){
		System.out.println(name);
	}
}

主测试类:

package agentTest;

public class mainTest {
	public static void main(String[] args) {
		User u=new User("佳佳");
		u.myName();
	}
}

下面是重点:

在启动参数中配置javaagent:

右键项目->Run as->Run configurations

image.png

image.png


运行结果:

image.png


评论区
请写下您的评论...
暂无评论...
猜你喜欢
java基础 2023 java调用c/c++类库(JNI)1.在java项目下创建native方法packagejni;/***@authorjiajia*/publicclassJniTest
其他 3819 1.动态编译从JDK1.6开始引入了用Java代码重写的编译器接口,使得我们可以在运行时编译Java源码,然后用类加载器进行加载,让Java语言更具灵活性,能够完成许多高级的操作。2.本次要实现
official 873 而不用频率来表示所使用的光载波。这样就得出了波分复用这一名词。最,人们只能在一根光纤上复用两路光载波信号。这种复用方式称为波分复用WDM。随着的发展,在一根光纤上复用的光载波信号的路数越来越多
weblog 1023 级java攻城尸,熟练使用各种框架,并知道它们实现的原理。jvm虚拟机原理、调优,懂得jvm能让你写出性能更好的代码;池,什么对象池,连接池,线程池...:;java反射,写框架必备的,但是
nginx,前端,java基础 1230   基于javanio+netty+websocket+protobuf+javascript等实现前后端高性能实时数据传输的demo模型。  github地址:https
official 986   基于javanio+netty+websocket+protobuf+javascript等实现前后端高性能实时数据传输的demo模型。  github地址:https
spring/springmvc 5768 springmvc启动时从数据库中始化系统常量设计的目标是,把项目的系统常量配置,放在数据库中,在项目始化时从项目中获取配置信息,利用反射,把key-value对应的值自动封装进配置类。1
java虚拟机(jvm) 4942 模块称为“类加载器”。类加载器可以说是Java语言的一项创新,也是Java语言流行的重要原因之一,它最是为了满足JavaApPlet的需求而开发出来的。虽然目前JavaApplet基本上已经“死掉
归档
2018-11  12 2018-12  33 2019-01  28 2019-02  28 2019-03  32 2019-04  27 2019-05  33 2019-06  6 2019-07  12 2019-08  12 2019-09  21 2019-10  8 2019-11  15 2019-12  25 2020-01  9 2020-02  5 2020-03  16 2020-04  4 2020-06  1 2020-07  7 2020-08  13 2020-09  9 2020-10  5 2020-12  3 2021-01  1 2021-02  5 2021-03  7 2021-04  4 2021-05  4 2021-06  1 2021-07  7 2021-08  2 2021-09  8 2021-10  9 2021-11  16 2021-12  14 2022-01  7 2022-05  1 2022-08  3 2022-09  2 2022-10  2 2022-12  5 2023-01  3 2023-02  1 2023-03  4 2023-04  2 2023-06  3 2023-07  4 2023-08  1 2023-10  1 2024-02  1 2024-03  1
标签
算法基础 linux 前端 c++ 数据结构 框架 数据库 计算机基础 储备知识 java基础 ASM 其他 深入理解java虚拟机 nginx git 消息中间件 搜索 maven redis docker dubbo vue 导入导出 软件使用 idea插件 协议 无聊的知识 jenkins springboot mqtt协议 keepalived minio mysql ensp 网络基础 xxl-job rabbitmq haproxy srs 音视频 webrtc javascript
目录
没有一个冬天不可逾越,没有一个春天不会来临。最慢的步伐不是跬步,而是徘徊,最快的脚步不是冲刺,而是坚持。