当前位置:   article > 正文

JAVA面试小结三十四:java agent实现原理_java agent原理

java agent原理

目录

一、java agent介绍

二、Java Agent的原理

1、原理是什么?

2、实现agent启动方法

3、agent加载

4、启动时修改

5、运行时修改


一、java agent介绍

java agent本质上可以理解为一个插件,该插件就是一个精心提供的jar包,这个jar包通过JVMTI(JVM Tool Interface)完成加载,最终借助JPLISAgent(Java Programming Language Instrumentation Services Agent)完成对目标代码的修改。

java agent技术的主要功能如下:

  • 可以在加载java文件之前做拦截把字节码做修改

  • 可以在运行期将已经加载的类的字节码做变更

  • 还有其他的一些小众的功能

    • 获取所有已经被加载过的类

    • 获取所有已经被初始化过了的类

    • 获取某个对象的大小

    • 将某个jar加入到bootstrapclasspath里作为高优先级被bootstrapClassloader加载

    • 将某个jar加入到classpath里供AppClassloard去加载

    • 设置某些native方法的前缀,主要在查找native方法的时候做规则匹配

二、Java Agent的原理

1、原理是什么?

Java Agent的原理主要是通过Java的Instrumentation API和JVMTI(Java Virtual Machine Tool Interface)来实现的。

Java Agent是一种运行在JVM中的特殊程序,可以在运行时修改或分析类的字节码。通过Instrumentation API,Java Agent可以在类加载到JVM之前或之后,对类的字节码进行修改或分析,以实现各种功能,如性能监控、故障排查、代码热替换等。

JVMTI是JVM提供的一组原生接口,用于监控和控制JVM的运行状态。Java Agent可以通过JVMTI获取JVM的运行信息,如线程状态、内存使用情况等,以实现更加精细的控制和监控。

总的来说,Java Agent的原理是通过Instrumentation API和JVMTI,在运行时对类的字节码进行修改或分析,以实现各种功能。

  1. 编写Java Agent代码:首先需要编写Java Agent的代码,实现所需的功能。Java Agent的代码通常包括一个premain方法,该方法会在目标JVM启动之前被执行,可以在其中进行字节码修改或分析等操作。
  2. 打包Java Agent:将Java Agent代码打包成一个独立的jar文件,以便后续使用。
  3. 使用Java Agent:在启动目标JVM时,通过添加-javaagent参数来指定Java Agent的路径和名称,如:java -javaagent:/path/to/agent.jar MyApp。这样,JVM在启动时就会加载并执行Java Agent的代码。
  4. 调试和测试:在实际使用中,需要对Java Agent进行调试和测试,以确保其能够正确地工作并实现预期的功能。

通过java agent技术进行类的字节码修改最主要使用的就是Java Instrumentation API。下面将介绍如何使用Java Instrumentation API进行字节码修改。

2、实现agent启动方法

Java Agent支持目标JVM启动时加载,也支持在目标JVM运行时加载,这两种不同的加载模式会使用不同的入口函数,如果需要在目标JVM启动的同时加载Agent,那么可以选择实现下面的方法:

  1. [1] public static void premain(String agentArgs, Instrumentation inst);

  2. [2] public static void premain(String agentArgs);

JVM将首先寻找[1],如果没有发现[1],再寻找[2]。如果希望在目标JVM运行时加载Agent,则需要实现下面的方法:

  1. [1] public static void agentmain(String agentArgs, Instrumentation inst);

  2. [2] public static void agentmain(String agentArgs);

这两组方法的第一个参数AgentArgs是随同 “–javaagent”一起传入的程序参数,如果这个字符串代表了多个参数,就需要自己解析这些参数。inst是Instrumentation类型的对象,是JVM自动传入的,我们可以拿这个参数进行类增强等操作。

3、agent加载
  • 启动时加载

    • 启动参数增加-javaagent:[path],其中path为对应的agent的jar包路径

  • 运行中加载

    • 使用com.sun.tools.attach.VirtualMachine加载

4、启动时修改

启动时修改主要是在jvm启动时,执行native函数的Agent_OnLoad方法,在方法执行时,执行如下步骤:

  • 创建InstrumentationImpl对象

  • 监听ClassFileLoadHook事件

  • 调用InstrumentationImpl的loadClassAndCallPremain方法,在这个方法里会去调用javaagent里MANIFEST.MF里指定的Premain-Class类的premain方法

5、运行时修改

运行时修改主要是通过jvm的attach机制来请求目标jvm加载对应的agent,执行native函数的Agent_OnAttach方法,在方法执行时,执行如下步骤:

  • 创建InstrumentationImpl对象

  • 监听ClassFileLoadHook事件

  • 调用InstrumentationImpl的loadClassAndCallAgentmain方法,在这个方法里会去调用javaagent里MANIFEST.MF里指定的Agentmain-Class类的agentmain方法

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/546964
推荐阅读
相关标签
  

闽ICP备14008679号