Java agent入门及demo示例(附源码)

news2024/11/24 9:27:01

这里是weihubeats,觉得文章不错可以关注公众号小奏技术,文章首发。拒绝营销号,拒绝标题党

背景

继之前我们研究了下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的字节码编程开发才是最麻烦的。
后续我们也会学习字节码编程

参考

  • https://docs.oracle.com/javase/8/docs/platform/jvmti/jvmti.html#whatIs
  • https://github.com/apache/skywalking-java
  • https://www.cnblogs.com/crazymakercircle/p/16635330.html#autoid-h2-6-0-0

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/566892.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android 12系统源码_窗口管理(一)WindowManagerService的启动流程

前言 WindowManagerService是Android系统中重要的服务&#xff0c;它是WindowManager的管理者&#xff0c;WindowManagerService无论对于应用开发还是Framework开发都是重要的知识点&#xff0c;究其原因是因为WindowManagerService有很多职责&#xff0c;每个职责都会涉及重要…

RabbitMQ发送方确认机制

1、前言 RabbitMQ消息首先发送到交换机&#xff0c;然后通过路由键【routingKey】和【bindingKey】比较从而将消息发送到对应的队列【queue】上。在这个过程有两个地方消息可能会丢失&#xff1a; 消息发送到交换机的过程。消息从交换机发送到队列的过程。 而RabbitMQ提供了…

中国移动董宁:深耕区块链的第八年,我仍期待挑战丨对话MVP

区块链技术对于多数人来说还是“新鲜”的代名词时&#xff0c;董宁已经成为这项技术的老朋友。 董宁2015年进入区块链领域&#xff0c;现任中国移动研究院技术总监、区块链首席专家。作为“老友”&#xff0c;董宁见证了区块链技术多个爆发式增长和平稳发展的阶段&#xff0c;…

基于STC8G1K08A的水压检测系统

基于STC8G1K08A的水压检测系统 前言先来一饱眼福设计和硬件的选型压力传感器选择单片机的选择WIFI透传模块选择 核心代码的开发STC8G1K08A单片机代码读取水压传感器的电压计算对应电压水的压力值猪场水压正常、漏水、喝光水提醒功能的实现 数据通过ESP8266上报到云端代码的实现…

低功耗定时器(LPTIMER)

概述 LPTIM 是运行在Always-On 电源域下的16bits 低功耗定时/计数器模块。通过选择合适的工作时钟&#xff0c;LPTIM 在在各种低功耗模式下保持运行&#xff0c;并且只消耗很低的功耗。LPTIM 甚至可以在没有内部时钟的条件下工作&#xff0c;因此可实现休眠模式下的外部脉冲计数…

新手怎么玩转Linux

Linux是一个非常强大、灵活和可定制的操作系统&#xff0c;这使得它成为了程序员的首选操作系统之一。程序员喜欢使用Linux的原因有以下几点&#xff1a;开源、稳定性、安全性、命令行界面、社区支持。那么新手改如何玩转Linux呢&#xff1f;跟着我一起来看看吧。 以下是对新…

Meta 开源语音 AI 模型支持 1,100 多种语言

自从ChatGPT火爆以来&#xff0c;各种通用的大型模型层出不穷&#xff0c;GPT4、SAM等等&#xff0c;本周一Meta 又开源了新的语音模型MMS&#xff0c;这个模型号称支持4000多种语言&#xff0c;并且发布了支持1100种语言的预训练模型权重&#xff0c;最主要的是这个模型不仅支…

行业报告 | 2022文化科技十大前沿应用趋势(上)

文 | BFT机器人 前言 Introduction 文化科技是文化科技融合过程中诞生的系列新技术成果&#xff0c;是文化强国和科技强国两大战略的交又领域。2012 年 8月&#xff0c;科技部会同中宣部、财政部、文化部、广电总局、新闻出版总署发布《文化科技创新工程纲要》&#xff0c;开启…

为何AI无法完全理解人类情感?GPT-4能否理解人类的情绪?

在科幻小说和电影里&#xff0c;我们经常看到超级AI人工智能机器人可以理解、感知甚至模拟人类的情感&#xff0c;但在现实世界中&#xff0c;我们距离这个目标还有一段相当长的距离&#xff0c;即使是强大的GPT-4甚至未来的GPT-5。过高夸大AI的体验和性能&#xff0c;往往并不…

gin框架返回json

一、使用gin web框架开发的两种模式&#xff1a; 前端浏览器去请求服务器&#xff0c;服务器把完整的HTML文件的内容返回给前端浏览器Vue、reactor等前端框架都自己提前定义好模板&#xff0c;后端&#xff08;服务器&#xff09;只需要返回JSON格式的数据给前端框架即可&…

如何在MyEclipse中使用JavaScript编写代码?

MyEclipse v2022.1.0正式版下载 JavaScript 项目 在 MyEclipse 2021 及更高版本中&#xff0c;JavaScript 支持对大多数 JavaScript 源代码都是开箱即用的——不需要特殊的 JavaScript Eclipse 项目或 JavaScript facet。但是&#xff0c;我们建议使用jsconfig.json文件来指定…

SAP 物料主数据基本数据1视图 参数有效值 字段的作用测试 <转载>

原文链接&#xff1a;https://blog.csdn.net/weixin_40672823/article/details/104773643 1.在物料主数据基本数据1视图中有个字段 参数有效值 如下图 有什么用途? 这个字段作用主要用在 BOM里面&#xff0c;官方说明如下 看说明很难理解下面通过一个业务实例来说明 业务要…

HOOPS平台助力Xometry数字化转型:即时报价产品实现三维模型轻量化、Web端可视化!

所属行业&#xff1a;制造业 挑战&#xff1a;为在线客户的制造平台提供流畅的客户体验、支持使用多种类型CAD文件格式的不同客户群、根据模型提供准确的报价和可制造性反馈、快速准确地可视化定制零 解决方案&#xff1a; HOOPS Platform 提供web端和移动设备的3D数据转换、…

擎创技术流 | 一文读懂eBPF对kubernetes可观测的重要性

一、云原生技术发展的背景与问题 当前&#xff0c;云原生技术主要是以容器技术为基础围绕着 Kubernetes的标准化技术生态&#xff0c;通过标准可扩展的调度、网络、存储、容器运行时接口来提供基础设施&#xff0c;同时通过标准可扩展的声明式资源和控制器来提供运维能力。两层…

Servlet【最复杂的hello world】

目录 一、Hello World 1.创建项目 2.引入依赖 3.创建目录 4.编写代码 4.1 继承 HttpServlet 父类&#xff0c;重写 doGet 方法 4.2 在 doGet 中编写代码&#xff0c;打印 hello world 4.3 给 HelloServlet 加上注解 4.4 完整代码 5.打包代码 6.部署 7.验证程序 二…

分享一个403界面给大家

先看效果图&#xff08;说明&#xff1a;小鬼影会飘来飘去&#xff0c;长时间停留会有小惊喜&#xff0c;具体大家跑一下就知道&#xff09;&#xff1a; 代码如下&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UT…

depends_on 解决 docker 容器依赖问题

如果你经常使用docker-compose启动服务的话&#xff0c;可能会遇到下面的问题&#xff1a;服务 B 依赖服务 A&#xff0c;需要服务 A 先启动&#xff0c;再启动服务 B 举个例子&#xff0c;在部署 kafka 集群的时候&#xff0c;需要启动两个kafka&#xff0c;并使用zookeeper做…

基于云计算和物联网技术开发的智慧校园云平台源码

智慧校园系统是利用物联网和云计算&#xff0c;强调对教学、科研、校园生活和管理的数据采集、智能处理、为管理者和各个角色按需提供智能化的数据分析、教学、学习的智能化服务环境。它包含“智慧环境、智慧学习、智慧服务、智慧管理”等层面的内容。 文末获取联系 它描绘的是…

准备搞个大动作!

目前我们的会员群的同学越来越多&#xff0c;然后我们提供的内容已经从起步篇&#xff0c;趣味篇&#xff0c;工具篇到高级篇了。但是到了高级篇很多内容都跟编程相关&#xff0c;有一点门槛&#xff0c;如果单单看文字是肯定无法满足大家的需求。为了更好的服务大家&#xff0…

跃升数字生产力,九州云受邀出席闵行国际人才月

5月22日&#xff0c;由闵行人才工作领导小组办公室指导、中共闵行区马桥镇委员会及闵行区马桥镇人民政府主办、上海人工智能研究院协办的首届“大零号湾”国际人才月马桥人工智能周成功召开。 本届大会以“AI才共赢 智敬未来”为主题&#xff0c;探讨科技创新的最新动态和趋势&…