javaagent使用

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.mfbz.cn/a/558306.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

启明云端ESP32-S3+车载桥接器案例,能实现对车载产品集控

最近房车旅行很盛行&#xff0c;谁不想五一自驾游开车去外面玩&#xff1f;为了能提升用户体验&#xff0c;车企房车智能化升级越来越普遍&#xff0c;接下来小启给大家讲一个案例&#xff0c;启明云端ESP32-S3车载桥接器&#xff0c;感兴趣的可以看看。 一、ESP32-S3车载桥接器…

实验:使用FTP+yum实现自制yum仓库

实验准备 FTP服务器端&#xff1a;centos-1&#xff08;IP:10.9.25.33&#xff09; 客户端&#xff1a;centos-2 两台机器保证网络畅通&#xff0c;原yum仓库可用&#xff0c;已关闭防火墙和selinux FTP服务器端 ①安装vsftpd并运行&#xff0c;设定开机自启动 安装vsftpd…

免费ssl通配符证书申请教程

在互联网安全日益受到重视的今天&#xff0c;启用HTTPS已经成为网站运营的基本要求。它不仅保障用户数据传输的安全&#xff0c;提升搜索引擎排名&#xff0c;还能增强用户对网站的信任。通配符证书是一种SSL/TLS证书&#xff0c;用于同时保护一个域名及其所有下一级子域名的安…

​面试经典150题——对称二叉树

1. 题目描述 2. 题目分析与解析 2.1 思路一——递归 为了解决问题“检查一个二叉树是否是对称的”&#xff0c;我们需要判断树的左子树和右子树是否是彼此的镜像。这意味着树的左子树的左侧应该与右子树的右侧相同&#xff0c;左子树的右侧应该与右子树的左侧相同。 定义问题…

数字工厂管理系统的应用场景主要有哪些

随着信息技术的飞速发展&#xff0c;数字工厂管理系统逐渐成为了工业制造领域的一大亮点。这一系统集成了物联网、大数据、云计算、人工智能等先进技术&#xff0c;实现了对工厂生产流程的智能化、高效化管理。那么&#xff0c;数字工厂管理系统究竟在哪些应用场景中发挥着重要…

Unity 3D定点数物理引擎实战系列:BEPU物理引擎碰撞计算与碰撞规则的架构与设计

前面我们讲解了如何监听物理引擎的碰撞事件, 在物理引擎内核中如何架构与设计碰撞规则,使得物理Entity与周围的物理环境产生碰撞时&#xff0c;如何灵活的控制物理碰撞&#xff0c;本节給大家详细的讲解BEPUphysicsint 物理引擎内部是如何管理与控制碰撞规则的。本文主要讲解3个…

项目二:学会使用python爬虫请求库(小白入门级)

上一章已经了解python爬虫的基本知识&#xff0c;这一次让我们一起来学会如何使用python请求库爬取目标网站的信息。当然这次爬虫之旅相信我能给你带来不一样的体验。 目录 一、安装requests 库 简介 安装 步骤 1.requests的基本使用3步骤 2.查看所使用编码 3.设置编码…

Qt菜单栏

文章目录 创建菜单栏创建菜单并在菜单栏中添加创建子菜单并添加到菜单创建菜单项并在菜单中添加分割线实现简易的记事本 Qt 窗口是通过 QMainWindow类 来实现的 创建菜单栏 Qt 中的菜单栏是通过 QMenuBar 这个类来实现的&#xff0c;一个窗口最多只有一个菜单栏。 菜单栏包含…

动态库静态库linux

动态库静态库 静态库 静态库必须包含在可执行文件里&#xff0c;整个都要包含 缺点&#xff1a;消耗系统大&#xff0c;每个使用静态库的程序都要复制静态库&#xff08;浪费内存&#xff09; 影响使用场景&#xff1a; 在静态库内存小的时候&#xff0c;可以用来提升速度 制…

学习MQ异步

1.MQ异步调用的优势 事件驱动模式&#xff1a; 优势&#xff1a; 总结&#xff1a; 2.初识MQ 核心概念以及结构&#xff1a; 常见的消息模型&#xff1a; 基本消息队列模型&#xff1a; 生产者代码&#xff1a; Testpublic void testSendMessage() throws IOException, Timeo…

亿级电商实时数据分析平台构建实战

基于FlinkClickHouse构建亿级电商实时数据分析平台&#xff08;PC、移动、小程序&#xff09; 引用网络文章开启本课程的开篇&#xff1a; 在大数据分析领域中&#xff0c;传统的大数据分析需要不同框架和技术组合才能达到最终的效果&#xff0c;在人力成本&#xff0c;技术能…

比较转录组学方法推断基因共表达网络及其在玉米和水稻叶片转录组中的应用 TO-GCN时序分析-文献精读-8

Comparative transcriptomics method to infer gene coexpression networks and its applications to maize and rice leaf transcriptomes 比较转录组学方法推断基因共表达网络及其在玉米和水稻叶片转录组中的应用 TO-GCN时序分析&#xff0c;媲美加权基因共表达网络分析-WG…

2024.4.16

多进程并发服务器 #include<myhead.h> #define SER_IP "192.168.125.54" #define SER_PORT 8888 void handler(int signo) {if(signoSIGCHLD){while(waitpid(-1,NULL,WNOHANG)>0);} } int main(int argc, char *argv[]) {//将SIGCHLD信号与处理函数绑定if(…

数据孤岛是业务效率的无声杀手

数据孤岛是组织的一个常见问题&#xff0c;因为它们可能对数据可访问性、数据完整性和数据管理造成障碍。当组织内的不同部门或团队拥有用于存储数据的数据库或系统&#xff0c;并且没有用于所有数据的中央存储库时&#xff0c;就会出现数据孤岛。这可能会导致难以全面了解数据…

minio 报错The specified key does not exist.

minio 报错The specified key does not exist. 解决方法 检查是否把全路径包含进去了&#xff0c;桶的名称是bucketName只填写桶的名称就行了&#xff0c;objectName是文件的名称&#xff0c;只要填写文件名称就行了&#xff0c;不要填写全路径&#xff01;&#xff01;&#…

36. UE5 RPG在激活技能时使用蒙太奇动画

在上一篇文章里面&#xff0c;我们实现了一个简单的火球术&#xff0c;创建了火球术的火球&#xff0c;以及能发射它的技能。很简陋&#xff0c;在技能触发的时候&#xff0c;直接在武器的位置生成火球发射出去。在一篇文章里&#xff0c;我们要实现使用技能时&#xff0c;角色…

实验室信息系统源码 saas模式java+.Net Core版开发的云LIS系统全套源码可二次开发有演示

实验室信息系统源码 saas模式java.Net Core版开发的云LIS系统全套源码可二次开发有演示 一、技术框架 技术架构&#xff1a;Asp.NET CORE 3.1 MVC SQLserver Redis等 开发语言&#xff1a;C# 6.0、JavaScript 前端框架&#xff1a;JQuery、EasyUI、Bootstrap 后端框架&am…

梯度下降法法实现线性回归模型

一、线性回归模型 线性回归模型是一种预测性的建模技术&#xff0c;它研究的是因变量&#xff08;目标&#xff09;和自变量&#xff08;特征&#xff09;之间的关系。这种关系假设是线性的&#xff0c;意味着因变量可以通过一个或多个自变量的线性组合来预测。数学上&#xf…

视觉slam14讲-大纲-持续更新

视觉slam入门太难 数学理论编程知识计算机视觉知识 缺一不可&#xff0c;大家一起加油

暗区突围PC国际服怎么参与测试 怎么获取测试资格

暗区突围PC国际服怎么参与测试 怎么获取测试资格 《暗区突围》这款游戏是由腾讯魔方工作室开发的一款刺激的大逃杀射击类游戏&#xff0c;在游戏中玩家将扮演一名特种兵&#xff0c;需要在充满敌人的暗区中展开战斗&#xff0c;完成各种任务。游戏中玩家可以选择不同的武器和装…
最新文章