Java Agent
在java代码开发过程中,有些测试环境的bug,通过java jdwp( Java Debug Wire Protocol)进行远程调试。jdwp定义了调试器(debugger)和被调试的 Java 虚拟机(target vm)之间的通信协议。
Target vm 中运行着我们希望要调试的程序,它与一般运行的 Java 虚拟机没有什么区别,只是在启动时加载了 Agent JDWP 从而具备了调试功能。而 debugger 就是我们熟知的调试器,它向运行中的 target vm 发送命令来获取 target vm 运行时的状态和控制 Java 程序的执行。Debugger 和 target vm 分别在各自的进程中运行,他们之间的通信协议就是 JDWP。
JDWP 与其他许多协议不同,它仅仅定义了数据传输的格式,但并没有指定具体的传输方式。这就意味着一个 JDWP 的实现可以不需要做任何修改就正常工作在不同的传输方式上
Target vm 端,JDWP 模块必须以 Agent library 的形式在 Java 虚拟机启动时加载,并且它必须通过 Java 虚拟机提供的 JVMTI 接口实现各种 debug 的功能,所以必须使用 C/C++ 语言编写。而 debugger 端就没有这样的限制,可以使用任意语言编写,只要遵守 JDWP 规范即可。JDI(Java Debug Interface)就包含了一个 Java 的 JDWP debugger 端的实现,JDK 中调试工具 jdb 也是使用 JDI 完成其调试功能的。
JDWP的更深介绍参考: https://www.jianshu.com/p/134bd5b913c5
JDWP使用
服务器端
服务器端需要加载jdwp,设置方式如下:
CMD java -Djava.security.egd=file:/dev/./urandom $TRACK -jar $JAVA_OPTS -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=9052 data-assets-biz.jar
需要加载jdwp agent。
参数说明:
- transport:指定了调试数据的传送方式
- dt_socket:是指用SOCKET模式
- address: 端口或者HOST:PORT
- server=y/n VM 是否需要作为调试服务器执行。
- suspend=y/n 在调试客户端建立连接之后是否挂起。
本地端
IDEA 配置调试。
进行断点调试时,远程服务器会挂起。
Agent
jdwp使用的是agent技术。在JDK1.5以后,可以使用agent技术构建一个独立于应用程序的代理程序(即为Agent),用来协助监测、运行甚至替换其他JVM上的程序。使用它可以实现虚拟机级别的AOP功能。
Agent分为两种,一种是在主程序之前运行的Agent,一种是在主程序之后运行的Agent(前者的升级版,1.6以后提供)。
主程序
package study;public class AgentTest {public static void main(String[] args) {System.out.println("this is main process");}
}
在主程序运行之前的代理程序
1、编写agent程序
package agent;import java.lang.instrument.Instrumentation;public class TestAgent {public static void premain(String agentArgs, Instrumentation ins){System.out.println("premain start...");System.out.println(agentArgs);}
}
2、配置MANIFEST.MF
<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version>3.2.0</version><configuration><archive><manifest><addClasspath>true</addClasspath></manifest><manifestEntries><Premain-Class>agent.TestAgent</Premain-Class></manifestEntries></archive></configuration></plugin></plugins></build>
3、主程序加载agent程序
java -cp ./agent-test-0-1.0.jar -javaagent:./agent-test-pre-1.0.jar=x study.AgentTest
输出:
premain start...
x
this is main process
agent详解
参数 javaagent 可以用于指定一个 jar 包,并且对该 java 包有2个要求:
- 这个 jar 包的MANIFEST.MF 文件必须指定 Premain-Class 项。
- Premain-Class 指定的那个类必须实现 premain()方法。
重点就在 premain 方法,也就是我们今天的标题。从字面上理解,就是运行在 main 函数之前的的类。当Java 虚拟机启动时,在执行 main 函数之前,JVM 会先运行 -javaagent 所指定 jar 包内 Premain-Class 这个类的 premain 方法,其中,该方法可以签名如下:
1.public static void premain(String agentArgs, Instrumentation inst)
2.public static void premain(String agentArgs)
JVM 会优先加载 1 签名的方法,加载成功忽略 2,如果1 没有,加载 2 方法。
在主程序运行之后的代理程序
premain 只能在类加载之前修改字节码,类加载之后无能为力,只能通过重新创建ClassLoader 这种方式重新加载。而 agentmain 就是为了弥补这种缺点而诞生的。简而言之,agentmain 可以在类加载之后再次加载一个类,也就是重定义,你就可以通过在重定义的时候进行修改类了,甚至不需要创建新的类加载器,JVM 已经在内部对类进行了重定义。
但是这种方式对类的修改是由限制的,对比原来的老类,由如下要求:
1.父类是同一个;
2. 实现的接口数也要相同;
3. 类访问符必须一致;
4. 字段数和字段名必须一致;
5. 新增的方法必须是 private static/final 的;
6. 可以删除修改方法;
可以看的出来,相比较重新创建类加载器,限制还是挺多的,最重要的字段是无法修改的。因此,使用的时候要注意。
但是,agentmain 还有一个强大的特点,就是目标程序什么都不需要管,就能够被代理。还记得 premain 是如何使用的吗?需要在目标应用启动的时候增加 -javaagent 参数。虽说没有侵入性,但相比 agentmain 而言,还是有侵入性的,毕竟 agentmain 什么都不要。目标程序独立运行,什么都不用管。
1、编写agent程序
package agent;import java.lang.instrument.Instrumentation;public class TestAgent4 {public static void agentmain(String agentArgs , Instrumentation inst){System.out.println("load agent after main run.args=" + agentArgs);Class<?> [] classes = inst.getAllLoadedClasses();for(Class<?> c :classes){System.out.println(c.getCanonicalName());}System.out.println("agent run complete." );}
}
2、配置MANIFEST.MF
<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version>3.2.0</version><configuration><archive><manifest><addClasspath>true</addClasspath></manifest><manifestEntries><Agent-Class>agent.TestAgent4</Agent-Class></manifestEntries></archive></configuration></plugin></plugins></build>
3、主程序加载agent程序
package study;public class AgentTest {public static void main(String[] args) {System.out.println("this is main process");List<VirtualMachineDescriptor> list = VirtualMachine.list();for (VirtualMachineDescriptor vmd : list) {if (vmd.displayName().endsWith("AccountMain")) {VirtualMachine virtualMachine = VirtualMachine.attach(vmd.id());virtualMachine.loadAgent("F:\\agent-test-post-1.0.jar");System.out.println("ok");virtualMachine.detach();}}}
}
需要先attach到一个VM,再加载agent。不是把agent加载到本VM。
输出:
MANIFEST.MF参考:https://blog.csdn.net/demon7552003/article/details/106568285
Java Agent相关推荐
- 写那么多年Java,还不知道啥是Java agent 的必须看一下!
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者信息:张帅,花名洵澈,国际化中台事业部高级开发工程师,负责物流 ...
- 我的天,你工作5年了,连Java agent都不知道...
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 # 引言 在本篇文章中,我会通过几个简单的程序来说明 agent ...
- java实现扫地agent_如何实现java agent?分享java agent的使用案例
java agent如何实现?1.实现java agent需要实现premain方法:2.必须在MANIFEST.MF文件中有Premain-Class. 在字节码这个层面对类和方法进行修改的技术,能 ...
- 说实话,你工作5年,不知道什么是Java agent技术,让我很吃惊...
注:本文定义-在函数执行前后增加对应的逻辑的操作统称为MOCK. 引子 在某天与QA同学进行沟通时,发现QA同学有针对某个方法调用时,有让该方法停止一段时间的需求,我对这部分的功能实现非常好奇,因此决 ...
- 通过使用Byte Buddy,便捷地创建Java Agent
Java agent是在另外一个Java应用("目标"应用)启动之前要执行的Java程序,这样agent就有机会修改目标应用或者应用所运行的环境.在本文中,我们将会从基础内容开始, ...
- idea git 过滤target_IDEA + maven 零基础构建 java agent 项目
Java Agent(java 探针)虽说在 jdk1.5 之后就有了,但是对于绝大多数的业务开发 javaer 来说,这个东西还是比较神奇和陌生的:虽说在实际的业务开发中,很少会涉及到 agent ...
- Java agent初探
点击上方"朱小厮的博客",选择"设为星标" 后台回复"加群"获取公众号专属群聊入口 来源:阿里巴巴中间件 在本篇文章中,我会通过几个简单的程 ...
- java 字节码增强原理_深入浅出Java探针技术1--基于java agent的字节码增强案例
Java agent又叫做Java 探针,本文将从以下四个问题出发来深入浅出了解下Java agent 一.什么是java agent? Java agent是在JDK1.5引入的,是一种可以动态修改 ...
- JVM插桩之二:Java agent基础原理
Javaagent只要作用在class被加载之前对其加载,插入我们需要添加的字节码. Javaagent面向的是我们java程序员,而且agent都是用java编写的,不需要太多的c/c++编程基础, ...
- java agent技术原理及简单实现
注:本文定义-在函数执行前后增加对应的逻辑的操作统称为MOCK 1.引子 在某天与QA同学进行沟通时,发现QA同学有针对某个方法调用时,有让该方法停止一段时间的需求,我对这部分的功能实现非常好奇,因此 ...
最新文章
- 【杂谈】裸辞一年后,分享一下我的心态
- CowNew开源-sql解析引擎和cownewsql阶段成果汇报
- 如何给Typora安装主题
- tensorflow 之 ValuError: At least two variables have the same name: bottom/bn1/beta_power0 等
- git stash命令的用法
- 神奇的python(三)之Python扩展C/C++库(C转换为Python)
- [乱弹琴]关于2的讨论
- 动手学深度学习 v2 PDF版本
- DOS命令和linux
- 微信小程序图片上传至mysql数据库
- for(int i = 0;i 10;i++)和int i;for(i = 0;i 10;i++)
- 谷歌浏览器崩溃之后卸载无法重装的解决方法
- word中插入的图片会覆盖文字
- Java五子棋(局域网)
- win10蓝牙功能不见了_Win10 2004更新了什么?新功能新特性汇总
- @Before和@After的区别
- 正则表达式(附匹配手机号和HTML标签)
- win系统快捷键大全
- 爬虫实战1:爬取糗事百科段子
- 朴素贝叶斯 实现 垃圾邮件分类