根据Java1.5的JavaAgent创建自定义的agent例子

一:什么是JavaAgent

     JavaAgent顾名思义就是Java探针技术,我理解的是,通过一个JavaAgent探针类,可以在java虚拟机启动之前,或者运行的时候植入这个探针类,对jvm做一些特别的操作,如动态改变字节码文件这种,要想植入,肯定是通过jvm参数来搞了

     使用JavaAgent的技术的项目我目前知道的是SkyWalking,dubbo用没用我没印象了

一、创建一个自定义的anget让JavaAgent在被代理程序在JVM运行启动的时候,做一些操作

1、创建一个Maven空项目不选模版直接next(也可以是纯净的Java项目注:不要选spring项目,否则打包和执行时都会报错)

 2、编写代理内容

package com.jacky;

import java.lang.instrument.Instrumentation;

public class PreMyProgram {
    /**
     * 该方法在main方法之前运行,与main方法运行在同一个JVM中
     * 并被同一个System ClassLoader装载
     * 被统一的安全策略(security policy)和上下文(context)管理
     *
     * @param agentOps
     * @param inst
     * @author jacky
     * @create  2021年12月20日
     */
    public static void premain(String agentOps,Instrumentation inst){

        System.out.println("====premain 方法执行");
        System.out.println(agentOps);
    }

    /**
     * 如果不存在 premain(String agentOps, Instrumentation inst)
     * 则会执行 premain(String agentOps)
     *
     * @param agentOps
     * @author jacky
     * @create  2021年12月20日
     */
   /* public static void premain(String agentOps){

        System.out.println("====premain方法执行2====");
        System.out.println(agentOps);
    }*/

}

3、定义MANIFEST.MF(呈现文件清单,指明入口类等)

自己写好一个MANIFEST.MF

Manifest-Version: 1.0
Premain-Class: com.jacky.PreMyProgram
Can-Redefine-Classes: true

然后在pom文件中指定自定义的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>org.jacky</groupId>
    <artifactId>java-agent-doem</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <!-- 指定定义的MANIFEST.MF文件(程序清清单文件)定制-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifestFile>
                            src/main/resources/META-INF/MANIFEST.MF
                        </manifestFile>
                        <manifest>
                            <addClasspath>true</addClasspath>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
            <!-- 打包是忽略test执行错误,防止测试执行错误打包终止-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <testFailureIgnore>true</testFailureIgnore>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

然后就可以mvn package了,打包得到jar包

整个文件结构:

二、创建被代理程序

我们创建一个可正常运行的springboot项目,打包得到mockStrategyCenter-0.0.1-SNAPSHOT.jar的包

为了方便测试 我们把两个代理包 和被代理包都放到相同文件夹

三、执行

如何执行?我们通过 -javaagent 参数来指定我们的Java代理包,值得一说的是 -javaagent 这个参数的个数是不限的,如果指定了多个,则会按指定的先后执行,执行完各个 agent 后,才会执行主程序的 main 方法。(此处我们指定了两个)

java -javaagent:./java-agent-doem-1.0-SNAPSHOT.jar=Hello1 -javaagent:./java-agent-doem-1.0-SNAPSHOT.jar=Hello2 -jar mockStrategyCenter-0.0.1-SNAPSHOT.jar

执行结果:

特别提醒:

(1)如果你把 -javaagent 放在 -jar 后面,则不会生效。也就是说,放在主程序后面的 agent 是无效的。

至此简单的通过javaAgent去实现被代理程序在JVM运行启动插入操作就实现了,后续我们可以通过结合asm字节码技术,实现对被代理程序源码编译后的字节码在jvm加载过程中的动态修改,去实现各种监控,插桩等场景

命令中的Hello1为我们传递给 premain 方法的字符串参数。

至此,我们会使用 javaagent 了,但是单单看这样运行的效果,好像没有什么实际意义嘛。

我们可以用 javaagent 做什么呢?下篇文章我们来介绍如何在项目中应用 javaagent。


最后说一下,还有一种,在main方法执行后再执行代理的方法,因为不常用,而且主程序需要配置 Agent-Class,所以不常用,如果需要自行了解下 agentmain(String agentArgs, Instrumentation inst) 方法。


 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值