javaagent使用

news2025/1/19 3:16:52

Java Agent是什么?

在这里插入图片描述

Java Agent是Java平台提供的一个强大工具,它可以在运行时修改或增强Java应用程序的行为。是在JDK1.5以后引入的,它能够在不影响正常编译的情况下修改字节码,相当于是在main方法执行之前的拦截器,也叫premain,也就是会先执行premain方法然后再执行main方法。
使用javaagent可以用于执行一个jar包,并且对这个java包有两个要求:

  • jar包的MANIFEST.MF文件必须指定Premain-Class项
  • Premain-Class指定的那个类必须实现premain()方法
    当程序启动的时候,JVM会首先检查-javaagent所指定的jar包内Premain-Class这个类中的premain方法。

Java Agent的使用场景

  • 代码注入增强:允许在程序运行时对字节码进行操作,可以实现功能的增强。
  • 性能监控调优:可以监控应用程序方法执行时间、调用次数,类加载的一些信息进行性能检测,以及对一些问题的定位分析,比如一些性能监控和诊断工具如Pinpoint、Skywalking、Zipkin、Arthas等。
  • 日志记录审计:Java Agent可以在方法执行前后记录方法的调用信息,包括方法名、参数、返回值等,动态记录应用程序的运行日志。

Java Agent的简单使用

1.基于 Instrumentation 接口和premain()方法实现

新建一个maven项目,添加maven-jar-plugin插件依赖,用于打包并生成MANIFREST.MF文件。

<build>
        <finalName>agenttestone</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.2.0</version>
                <configuration>
                    <archive>
                        <!--自动添加META-INF/MANIFEST.MF -->
                        <manifest>
                            <addClasspath>true</addClasspath>
                        </manifest>
                        <manifestEntries>
                            <!--permain方法所在类的完全限定名-->
                            <Premain-Class>com.yifanghub.agent.PremainTest</Premain-Class>
                            <Agent-Class>com.yifanghub.agent.PremainTest</Agent-Class>
                            <Can-Redefine-Classes>true</Can-Redefine-Classes>
                            <Can-Retransform-Classes>true</Can-Retransform-Classes>
                        </manifestEntries>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>

其中manifestEntries配置了一些属性
<Premain-Class>包含premain方法的类(类的全路径名)
<Agent-Class>包含agentmain方法的类(类的全路径名)
<Can-Redefine-Classes>是否可以重定义此代理所需的类,默认为false
<Can-Retransform-Classes>是否可以重新转换此代理类所需的类,默认为false

新建premain方法测试类,其中premain方法,agentArgs可以通过命令行传入

package com.yifanghub.agent;
import java.lang.instrument.Instrumentation;

public class PremainTest {
    public static void premain(String agentArgs, Instrumentation inst) {
        System.out.println("premain执行---->");
       System.out.println("Hello agent test,agentArgs="+agentArgs);
    }
}

新建main方法测试类(新建一个项目)

package com.yifanghub.agent;

public class PremainAgent {
    public static void main(String[] args) {
        System.out.println("agent测试走起,main方法执行");
    }
}

执行main方法,打印如下:

agent测试走起,main方法执行

idea配置:编辑启动类->Add VMOptions

-javaagent:D:\javaagent-demo\javaagent-demo-1.0-SNAPSHOT.jar=123

运行程序,打印如下:
premain执行---->
Hello agent test,agentArgs=123
agent测试走起,main方法执行

注意事项

  1. agent的方法名必须是premain,否则会报错。

  2. agent抛出异常,会导致主程序的启动失败。

  3. premain方法只允许以下两种定义方式

     1)public static void premain(String agentArgs, Instrumentation inst)
     2)public static void premain(String agentArgs)
      JVM 会优先加载带有Instrumentation参数的方法1,加载成功忽略 2,如果1 没有,加载 2 方法。
    

2.基于 Attach 接口和agentmain()方法实现

JDK 1.6后引入了agentmain模式,同样提供了一个agentmain方法,可以在main方法执行之后运行

public static void agentmain (String agentArgs, Instrumentation inst)
public static void agentmain (String agentArgs)

1)创建agentmian方法类

import java.lang.instrument.Instrumentation;

public class AgentmainTest {
    public static void agentmain(String agentArgs, Instrumentation inst) {
        System.out.println("agentmain执行---->");
        System.out.println("Hello I am agentmain test,agentArgs="+agentArgs);
    }
}

将上面代码打包,名字为:javaagent-demo2-1.0-SNAPSHOT.jar

2)创建被注入的main方法测试类(新建一个项目),这里主要使用一个for循环打印,让程序处于一直运行状态

public class MainTest {
    public static void main(String[] args) {
        System.out.println("开始执行mian");

        for (int i = 1; i <= 100000; i++) {

            System.out.println("第 " + i+ " 次循环");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

3)创建attach项目,编写main方法
这里用到了com.sun.tools.attach 包下面的VirtualMachine工具类来实现,该类表示一个Java虚拟机对象,该类的一些接口如下:

  • list():获取当前所有JVM列表
  • attach():根据进程id,连接到jvm上
  • detach():断开连接
  • loadAgent():加载agent

如果idea里面不能导入VirtualMachine类,导入JDK里面lib下的tool.jar包即可
在这里插入图片描述
attach方法如下:

import com.sun.tools.attach.*;
import java.io.IOException;
import java.util.List;

public class AgentDemo4Test {
    public static void main(String[] args) throws IOException, AttachNotSupportedException, AgentLoadException, AgentInitializationException {
        System.out.println("AgentDemo4Test");
        List<VirtualMachineDescriptor> list = VirtualMachine.list();
        for (VirtualMachineDescriptor vmd : list) {
            if(vmd.displayName().equals("agent.MainTest")){
                System.out.println(vmd.displayName());
                VirtualMachine vm = VirtualMachine.attach(vmd.id());
                vm.loadAgent("D:\\javaagent-demo2-1.0-SNAPSHOT.jar","123456");
                vm.detach();
            }
        }
    }
}

4)启动运行MainTest类(第2步打印for循环的程序),然后执行上面AgentDemo4Test类的main方法,输出如下:
在这里插入图片描述
可以看到,我们的agentmain方法的代理已经生效,其中attach方法可以连接到一个正在运行的Java进程当中,之后便可以通过loadAgent方法将我们的jar包注入到对应的进程当中,然后被注入的进程就好调用jar包里的agentmain方法。

注意事项

  • agentmain()​方法会在加载之时立即执行,如果agentmain执行失败或抛出异常,JVM 会忽略掉错误,不会影响到正在运行的程序。

参考:https://www.cnblogs.com/LittleHann/p/17462796.html

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

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

相关文章

Python | Leetcode Python题解之第32题最长有效括号

题目&#xff1a; 题解&#xff1a; class Solution:def longestValidParentheses(self, s: str) -> int:stack[]maxL0nlen(s)tmp[0]*n #标记数组cur0for i in range(n):if s[i](:stack.append(i)else:if stack:jstack.pop()if s[j](:tmp[i],tmp[j]1,1 #匹配成…

【C++】:C++关键字,命名空间,输入输出,缺省参数

目录 一&#xff0c;C关键字(C98)二&#xff0c;命名空间2.1 命名冲突2.2 关键字namespace2.2.1 命名空间中可以定义变量/函数/类型2.2.2 命名空间可以嵌套2.2.3 同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。 2.3 命名空间的使用2.3.1 指定…

多模态AnyGPT——整合图像、语音和文本多模态大规模语言模型算法原理与实践

概述 大规模语言模型在理解和生成人类语言方面具有非凡的能力&#xff0c;但迄今为止&#xff0c;它们的能力主要局限于文本处理。然而&#xff0c;现实世界是一个多模式的环境&#xff0c;信息通过视觉、听觉和触觉等多种感官进行交换。融入这种多样性是开发下一代系统的主要…

桥接模式【结构型模式C++】

1.概述 桥接模式是一种结构型设计模式&#xff0c;是用于把抽象化与实现化解耦&#xff0c;使得二者可以独立变化。这种类型的设计模式属于结构型模式&#xff0c;它通过提供抽象化和实现化之间的桥接结构&#xff0c;来实现二者的解耦。 这种模式涉及到一个作为桥接的接口&am…

高斯溅射融合之路(一)- webgl渲染3d gaussian splatting

大家好&#xff0c;我是山海鲸的技术负责人。之前已经写了一个GIS融合系列。其实CesiumJS的整合有相当的难度&#xff0c;同时也有很多方面的工作&#xff0c;很难在几篇文章内写完&#xff0c;整个山海鲸团队也是投入了接近两年的时间&#xff0c;才把周边整套工具链进行了完善…

算法复杂度分析笔记

基本定义间的关系 算法介绍 算法分析 时间复杂度 用数量级刻画&#xff1a;忽略所有低次幂项和系数 eg1: eg2: eg3: eg4: 小结 空间复杂度 eg: 总结

Vue3从入门到实践:深度了解新组件

1.Teleport 概念&#xff1a;Teleport&#xff08;传送门&#xff09;是一个新的特性&#xff0c;用于在DOM中的任意位置渲染组件。它允许你将组件的内容渲染到DOM中的另一个位置&#xff0c;而不受组件层次结构的限制。 下面举出例子解释&#xff1a; 1.新建App.vue文件作…

YOLOv9改进策略 | Neck篇 | 2024.1最新MFDS-DETR的HS-FPN改进特征融合层(轻量化Neck、全网独家首发)

一、本文介绍 本文给大家带来的改进机制是最近这几天最新发布的改进机制MFDS-DETR提出的一种HS-FPN结构&#xff0c;其是一种为白细胞检测设计的网络结构&#xff0c;主要用于解决白细胞数据集中的多尺度挑战。它的基本原理包括两个关键部分&#xff1a;特征选择模块和特征融合…

vue快速入门(三十一)vscod开发vue需要下载的插件

步骤很详细&#xff0c;直接上教程 上一篇 暂时就这两样足矣&#xff0c;有新的以后再更新&#xff08;别下载太多&#xff0c;可能会冲突&#xff09; 测试一下&#xff1a; 提示功能&#xff1a; 代码补全功能&#xff1a;

基于弹簧鞘复合纱和迁移学习算法的可穿戴人体重构和智能试衣系统

研究背景 在信息时代和元宇宙的背景下&#xff0c;虚拟服装设计对满足服装行业的个性化需求至关重要。与传统方法不同&#xff0c;虚拟试衣节省时间、方便客户&#xff0c;并提供多样化的款式。准确得测量人体围度并重构出人体的模型是虚拟试衣的关键。为了实现动态人体重构&a…

第Y7周:训练自己的数据集

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制&#x1f680; 文章来源&#xff1a;K同学的学习圈子 目录 一、下载YOLOv8 二、配置环境 三、准备工作 四、运行 出现报错&#xff1a;…

《QT实用小工具·三十一》基于QT开发的访客管理平台demo2

1、概述 源码放在文章末尾 该项目为访客管理平台demo&#xff0c;包含主界面、系统设置、警情查询、调试帮助、用户退出功能。 项目部分代码如下&#xff1a; #pragma execution_character_set("utf-8")#include "frmmain.h" #include "ui_frmmain…

使用不锈钢微型导轨的优势!

微型导轨是一种专门用于在紧凑空间内执行高精度的机器运动控制的导轨设备。其特点是尺寸小、精确度高、刚性好、平稳性好以及使用寿命长。微型导轨的材质种类多样&#xff0c;一般包括钢、不锈钢、铝合金等。目前来说&#xff0c;不锈钢材质的使用率最为频繁&#xff0c;那么使…

python中中英文打印对齐解决方案

在python中&#xff0c;有时候会出现中英文混合输出的情形&#xff0c;但是由于中文默认是全角格式&#xff08;一个中文字符占用两个字符宽度&#xff09;&#xff0c;这会对python原生的print函数带来一些障碍。尤其是用户用print对齐输出的时候&#xff0c;这种差异会导致文…

揭秘网红主播美颜工具:探秘美颜SDK的技术奥秘

在如今的网络直播平台上&#xff0c;越来越多的主播通过美颜工具来提升自己的形象&#xff0c;吸引更多的粉丝和观众。美颜技术的不断发展使得主播们能够在镜头前展现出更加完美的容颜&#xff0c;让观众眼前一亮。 一、美颜SDK的概念 美颜SDK&#xff0c;即美颜软件开发工具…

Bert语言大模型基础

一、Bert整体模型架构 基础架构是transformer的encoder部分&#xff0c;bert使用多个encoder堆叠在一起。 主要分为三个部分&#xff1a;1、输入部分 2、注意力机制 3、前馈神经网络 bertbase使用12层encoder堆叠在一起&#xff0c;6个encoder堆叠在一起组成编码端&#xf…

存储过程的使用(一)

目录 不带参数的存储过程 创建一个存储过程&#xff0c;向数据表 dept 中插入一条记录 带 IN 参数的存储过程 在存储过程中接受来自外部的数值&#xff0c;在存储过程中判断该数值是否大于零并显示 输入一个编号&#xff0c;查询数据表emp中是否有这个编号&#xff0c;如果…

【QT进阶】Qt Web混合编程之使用ECharts显示各类折线图等

往期回顾 【QT进阶】Qt Web混合编程之QWebEngineView基本用法-CSDN博客 【QT进阶】Qt Web混合编程之CMake VS2019编译并使用QCefView&#xff08;图文并茂超详细版本&#xff09;-CSDN博客【QT进阶】Qt Web混合编程之html、 js的简单交互-CSDN博客 【QT进阶】Qt Web混合编程之使…

【Web】2022DASCTF Apr X FATE 防疫挑战赛 题解(全)

目录 warmup-php soeasy_php warmup-java warmup-php spl_autoload_register函数实现了当程序遇到调用没有定义过的函数时&#xff0c;会去找./class/函数名.php路径下的php文件&#xff0c;并把它包含在程序中。 拿到附件拖进Seay里自动审计一下 显然利用终点为evaluateExp…

【面试经典 150 | 二叉树层序遍历】二叉树的右视图

文章目录 写在前面Tag题目来源解题思路方法一&#xff1a;层序遍历方法二&#xff1a;深度优先搜索 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一些对于…