初识javaagent技术

硅谷探秘者 1589 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基础 1579 java调用c/c++类库(JNI)1.在java项目下创建native方法packagejni;/***@authorjiajia*/publicclassJniTest
其他 2617 1.动态编译从JDK1.6开始引入了用Java代码重写的编译器接口,使得我们可以在运行时编译Java源码,然后用类加载器进行加载,让Java语言更具灵活性,能够完成许多高级的操作。2.本次要实现
official 195 而不用频率来表示所使用的光载波。这样就得出了波分复用这一名词。最,人们只能在一根光纤上复用两路光载波信号。这种复用方式称为波分复用WDM。随着的发展,在一根光纤上复用的光载波信号的路数越来越多
weblog 587 级java攻城尸,熟练使用各种框架,并知道它们实现的原理。jvm虚拟机原理、调优,懂得jvm能让你写出性能更好的代码;池,什么对象池,连接池,线程池...:;java反射,写框架必备的,但是
nginx,前端,java基础 363   基于javanio+netty+websocket+protobuf+javascript等实现前后端高性能实时数据传输的demo模型。  github地址:https
official 308   基于javanio+netty+websocket+protobuf+javascript等实现前后端高性能实时数据传输的demo模型。  github地址:https
spring/springmvc 5160 springmvc启动时从数据库中始化系统常量设计的目标是,把项目的系统常量配置,放在数据库中,在项目始化时从项目中获取配置信息,利用反射,把key-value对应的值自动封装进配置类。1
java虚拟机(jvm) 3656 模块称为“类加载器”。类加载器可以说是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
标签
算法基础 linux 前端 c++ 数据结构 框架 数据库 计算机基础 储备知识 java基础 ASM 其他 深入理解java虚拟机 nginx git 消息中间件 搜索 maven redis docker dubbo vue 导入导出 软件使用 idea插件 协议 无聊的知识 jenkins springboot mqtt协议 keepalived minio mysql ensp 网络基础
目录
余生别太较劲,放过自己 才会幸福。