Java agent的入门与demo演示详解

 更新时间:2023年05月26日 10:00:49   作者:weihubeats  
Java Agent 是 Java 1.5 版本之后引⼊的特性,其主要作⽤是在class被加载之前对其拦截,这篇文章主要介绍了agent的简单使用,需要的可以参考下

背景

继之前我们研究了下skywalking是什么以及skywalking如何监控skywalking

我们并没有探讨过多的skywalking原理 实际上skywalking的实现原理就是javaagent所以我们再继续研究skywalking之前还是先补补基础吧

什么是java 的agent

Java Agent 是 Java 1.5 版本之后引⼊的特性,其主要作⽤是在class被加载之前对其拦截,已插⼊我们的监听字节码

官方文档: https://docs.oracle.com/javase/8/docs/platform/jvmti/jvmti.html#whatIs

用通俗易懂的话来说就是,我们可以不改变原有项目的任何代码,对项目进行一些增强操作

agent的加载时机

Java的Agent加载时机分别有两处

  • 加载时刻增强(JVM 启动时加载)
  • 动态增强(JVM 运行时加载)

我们要如何进行编码来实现我们的增强逻辑呢? JVM提供了几个入口函数

加载时刻增强(JVM 启动时加载)

JVM 启动时加载启动时的入口方法提供了两个

 // 方法一
public static void premain(String agentArgs, Instrumentation inst);
// 方法二
public static void premain(String agentArgs);

这两个函数的优先级是,如果没有方法一,则寻找方法二

动态增强(JVM 运行时加载)

JVM 运行时加载也提供了两个入口方法

// 方法一
public static void agentmain(String agentArgs, Instrumentation inst);
// 方法二
public static void agentmain(String agentArgs);

与上面JVM 启动时加载的加载机制一样。如果没有方法一,则寻找方法二

如果刚接触agent大家可能还是有点懵 没关系,下面我们先带大家写一个简单的demo来看看效果,这样就更容易理解

demo演示

如果不想编写我这里也提供了直接下载的源码

源码地址:https://github.com/weihubeats/weihubeats_demos/tree/master/java-demos/agent-demo

项目结构

核心demo

package com.weihubeats.agent.demo;

import java.lang.instrument.Instrumentation;

public class AgentDemo {


    public static void premain(String agentArgs, Instrumentation inst) {
        System.out.println("========= 小奏技术1 premain init ========");
        System.out.println("agentArgs:="+agentArgs);

    }
    
    public static void premain(String agentArgs) {
        System.out.println("========= 小奏技术2 premain agentArgs init ========");
        System.out.println("agentArgs:="+agentArgs);
    }
    
}

注意我们写完代码之后需要创建一个resources/META-INF.MANIFEST.MF文件

文件内容如下

Manifest-Version: 1.0
Can-Redefine-Classes: true   # true表示能重定义此代理所需的类,默认值为 false(可选)
Can-Retransform-Classes: true    # true 表示能重转换此代理所需的类,默认值为 false (可选)
Premain-Class:  com.weihubeats.agent.demo.AgentDemo

这样我们的代码就编写完成了。这时候我们需要将整个项目打成一个jar,然后给其他项目接入

需要注意如果我们要测试agentmain的使用,需要手动调用触发

import com.sun.tools.attach.VirtualMachine;

public class Main {

  public static void main(String[] args) {
    // 获取当前 Java 进程的 PID
    String pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0]; 
    
    // 使用运行中的 JVM PID 创建一个 VirtualMachine 对象
    VirtualMachine vm = VirtualMachine.attach(pid);
    
    // 加载并附加 Java Agent 到运行中的 JVM
    vm.loadAgent("path/to/your/agent.jar");
    
    // 现在 agentmain 方法应该已经被调用了
  }
}

从这里可以看到agentmain的增强方式触发有点麻烦,所以我们就暂>时不演示这种触发方式了 skywalking的实现也是基于premain去实现的

打包

pom添加打包插件

<build>
        <finalName>java-agent-demo</finalName>
        <plugins>
            <plugin>
                <artifactId>maven-shade-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <shadedArtifactAttached>false</shadedArtifactAttached>
                            <createDependencyReducedPom>true</createDependencyReducedPom>
                            <createSourcesJar>true</createSourcesJar>
                            <shadeSourcesContent>true</shadeSourcesContent>
                            <transformers>
                                <transformer
                                    implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <manifestEntries>
                                        <Premain-Class>com.weihubeats.agent.demo.AgentDemo</Premain-Class>
                                        <Can-Redefine-Classes>true</Can-Redefine-Classes>
                                        <Can-Retransform-Classes>true</Can-Retransform-Classes>
                                    </manifestEntries>
                                </transformer>
                            </transformers>
                            <!--<artifactSet>
                                <excludes>
                                    <exclude>*:gson</exclude>
                                    <exclude>io.netty:*</exclude>
                                    <exclude>io.opencensus:*</exclude>
                                    <exclude>com.google.*:*</exclude>
                                    <exclude>com.google.guava:guava</exclude>
                                    <exclude>org.checkerframework:checker-compat-qual</exclude>
                                    <exclude>org.codehaus.mojo:animal-sniffer-annotations</exclude>
                                    <exclude>io.perfmark:*</exclude>
                                    <exclude>org.slf4j:*</exclude>
                                </excludes>
                                &lt;!&ndash; 将javassist包打包到Agent中 &ndash;&gt;
                                <includes>
                                    <include>javassist:javassist:jar:</include>
                                </includes>
                            </artifactSet>-->
                            <filters>
                                <filter>
                                    <artifact>net.bytebuddy:byte-buddy</artifact>
                                    <excludes>
                                        <exclude>META-INF/versions/9/module-info.class</exclude>
                                    </excludes>
                                </filter>
                            </filters>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

打包方式很简单,我们在项目根目录执行打包命令

mvn clean package

打完包后我们的项目target目录出现了我们的agent

spring boot 项目接入

我们在spring boot项目添加如下启动参数

-javaagent:/Users/weihu/Desktop/sofe/java/weihubeats_demos/java-demos/agent-demo/target/java-agent-demo.jar=xiaozouParam=xiaozou

然后我们启动参数,查看log

可以看到启动成功了

总结

java agent的增强主要用两种方式agentmainpremain大多应用程序应该是使用的premain,因为可以看到agentmain还需要应用系统自己添加代码去触发

agent的一些基础方法和接入使用,其实agent的字节码编程开发才是最麻烦的。 后续我们也会学习字节码编程

以上就是Java agent的入门与demo演示详解的详细内容,更多关于Java agent的资料请关注脚本之家其它相关文章!

相关文章

  • Mybatis-plus+通用mapper(tk.mybatis)的使用

    Mybatis-plus+通用mapper(tk.mybatis)的使用

    本文主要介绍了Mybatis-plus+通用mapper(tk.mybatis)的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧<BR>
    2024-03-03
  • java腾讯AI人脸对比对接代码实例

    java腾讯AI人脸对比对接代码实例

    这篇文章主要介绍了java腾讯AI人脸对比对接,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • Java中四种9*9乘法表的实现方式(附代码)

    Java中四种9*9乘法表的实现方式(附代码)

    这篇文章主要介绍了Java中四种9*9乘法表的实现方式(附代码),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • SpringBoot实现文件压缩处理详解

    SpringBoot实现文件压缩处理详解

    在工作我们经常会出现有多个文件,为了节省资源会将多个文件放在一起进行压缩处理,本文将使用SpringBoot实现文件压缩处理,感兴趣的可以了解下
    2024-11-11
  • 基于SSM实现学生管理系统

    基于SSM实现学生管理系统

    这篇文章主要为大家详细介绍了基于SSM实现学生管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-12-12
  • Mybatis和其他主流框架的整合使用过程详解

    Mybatis和其他主流框架的整合使用过程详解

    MyBatis最初是Apache的一个开源项目iBatis, 2010年6月这个项目由Apache Software Foundation迁移到了Google Code,这篇文章主要介绍了Mybatis和其他主流框架的整合使用,需要的朋友可以参考下
    2023-11-11
  • mybatis-plus条件构造器的操作代码

    mybatis-plus条件构造器的操作代码

    mybatis-plus提供了AbstractWrapper抽象类,提供了很多sql语法支持的方法,比如模糊查询,比较,区间,分组查询,排序,判断空,子查询等等,方便我们用面向对象的方式去实现sql语句,本文重点给大家介绍mybatis-plus条件构造器的操作代码,感兴趣的朋友一起看看吧
    2022-03-03
  • SpringBoot中的依赖管理详解

    SpringBoot中的依赖管理详解

    这篇文章主要介绍了SpringBoot中的依赖管理详解,传统的Spring框架实现一个Web服务,需要导入各种依赖JAR包,然后编写对应的XML配置文件等,相较而言,Spring Boot显得更加方便、快捷和高效,需要的朋友可以参考下
    2023-08-08
  • Java8 Lambda表达式详解及实例

    Java8 Lambda表达式详解及实例

    这篇文章主要介绍了Java8 Lambda表达式详解的相关资料,需要的朋友可以参考下
    2016-09-09
  • java spring mvc处理器映射器介绍

    java spring mvc处理器映射器介绍

    这篇文章主要介绍了java spring mvc处理器映射器,文章围绕equestMapping解析映射介绍展开源码内容,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-03-03

最新评论