网站首页 > java教程 正文
JavaAgent技术
JavaAgent是一种特殊的Java程序,是Instrumentation的客户端。它与普通Java程序通过main方法启动不同,JavaAgent并不是一个可以单独启动的程序,它必须依附在一个Java应用程序(JVM)上,与主程序运行在同一个进程中,通过Instrumentation API与虚拟机交互。
JVM启动时静态加载
对于JVM启动时加载的Agent模块代码,Instrumentation会通过premain方法传入代理程序,premain方法会在调用程序main方法之前被调用,同时Instrumentation包含agentmain方法实现字节码改写,二者的区别如下:
● premain 方 法 用 于 在 启 动 时 , 在 类 加 载 前 定 义 类 的TransFormer(转化器),在类加载的时候更新对应的类的字节码。
● agentmain方法用于在运行时进行类的字节码的修改,步骤分为注册类的TransFormer调用和retransformClasses函数进行类的重加载。
premain方法与agentmain方法相比有很大的局限性。premain方法仅限于应用程序的启动时,即main函数执行前。此时还有很多类没有被加载,而这些类使用premain方法是无法实现字节码改写的。
目前,主流的基于探针的监控系统都是基于这种方式实现的对应用的无侵入监控。我们知道程序的入口是main方法,而premain方法代表了在程序正式启动之前执行的动作,它同时具备类似AOP的能力。
Transformer提供字节码文件流转化的能力,如下图所示是Class文件转换图。
字节码改写
如上图所示,任何Class文件在加载时,都要经过premain这一代码转换环节。通过一系列的TransFormer转换,Class字节码文件流最终转变为我们期望的代码实现,然后被加载到JVM中。修改Class字节码文件流的动作是在Transformer中进行的。我们可以使用Javaassist技术修改字节码文件流(下一节介绍)。下面就是我们实现的一个类 , 实 现 了 带 Instrumentation 参 数 的 premain 方 法 。 调 用addTransformer方法对启动时所有的类进行拦截,示例代码如下:
JVM启动后动态Instrument机制
关于JVM启动后动态加载Agent的方法,Instrumentation会通过agentmain方法传入程序。agentmain方法在main函数开始运行后才被调用,其最大优势是可以在程序运行期间进行字节码的替换。
Attach API[1]实现动态注入的原理如下。
你的应用程序通过虚拟机提供的attach(pid)方法,可以将代理程序连接(attach)到一个运行中的Java进程上,之后便可以通过loadAgent(AgentJarPath)将Agent的jar包注入对应的进程,然后对应的进程会调用agentmain方法,如下图所示。
工程结构和上面premain的一样,编写AgentMainTest代码示例如下:
JavaAgent运行前启动加载代理程序的方法如下。
JavaAgent有两个启动时机,一个是在程序启动时通过-javaAgent参数启动代理程序;另一个是在程序运行期间通过Java Tool API中的Attach API动态启动代理程序。我们通过-javaAgent来指定我们编写的Agent的jar路径(./{Location}/Agent.jar)。这样在启动时,Agent就可以做定制化的字节码改动了。对于Spring Boot类内置容器的服务,可以使用下面方式:
在Tomcat启动时,它会读取CATALINA_OPTS环境变量,并将它加入启动命令中。在环境变量中添加如下信息:
Java程序运行后加载代理的方法如下。
程序启动之后,我们通过某种特定的手段加载Java Agent。这个特定的手段就是虚拟机的Attach API。这个API其实是JVM进程之间的沟通桥梁,它的底层通过Socket进行通信。JVM A可以发送一些指令给JVM B,JVM B收到指令之后,可以执行对应的逻辑,比如在命令行中经常使用的jstack、jcmd、jps等命令。因为是进程间通信,所以使用Attach API的也是一个独立的Java进程。下面是一个简单的实现,代码示例如下:
本文给大家讲解的内容是服务监控治理, JavaAgent技术
- 下篇文章给大家讲解的内容是服务监控治理,Javaassist技术
- 觉得文章不错的朋友可以转发此文关注小编;
- 感谢大家的支持!
- 上一篇: 如何开发一个轻量且高效的SDK
- 下一篇: 一篇文章,手把手教你运行百度离线人脸识别SDK-Java版
猜你喜欢
- 2025-01-06 IntelliJ IDEA详细配置图解,挖掘更多的功能
- 2025-01-06 SpringBoot集成开源IM框架MobileIMSDK,实现即时通讯IM聊天功能
- 2025-01-06 基于crudapi零代码平台后端Java SDK二次开发API认证和鉴权(二)
- 2025-01-06 微信开发最新Java SDK来了:WxJava3.9.0
- 2025-01-06 亚马逊 spapi — 生成 Java SDK
- 2025-01-06 OpenTelemetry Java SDK 高级用法
- 2025-01-06 Easysearch Java SDK 2.0.x 使用指南(三)
- 2025-01-06 一篇文章,手把手教你运行百度离线人脸识别SDK-Java版
- 2025-01-06 字节码增强技术之 Java Agent 入门
- 2025-01-06 如何开发一个轻量且高效的SDK
你 发表评论:
欢迎- 04-24Java Collections 工具类集合框架中常用算法解析
- 04-24桶排序的简单理解
- 04-24Java集合框架底层实现原理大揭秘
- 04-24Java 集合框架全面解析:选对数据结构,提升开发效率
- 04-24c#集合排序
- 04-24Java面试中常被问到的集合类深度解读
- 04-24VBA技术资料MF278:对集合进行排序
- 04-24Spring 最常用的 7 大类注解,史上最强整理
- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)