Java Agent Programming

2025年5月3日 | 阅读3分钟

什么是 Java Agent?

Java Agent 是一种可以帮助修改字节码的工具,因为它与 Java 程序并发运行。这些 Agent 可以通过使用 -javaagent 选项附加到 JVM,从而能够拦截 ClassLoaders 并在执行前对 ByteCODE 执行转换。

这种动态方法是非侵入性的,因此在应用程序的分析、日志记录、性能测量和监控以及更改正在运行的应用程序的各种特性等方面非常有用。

Agent 在以下任务中特别有用:

性能分析:在运行时获取数据,包括方法执行所花费的时间。

监控:为了 调试 和审计目的,我们可以在特定方法被调用时进行日志记录。

字节码操作:能够在不更改其源代码的情况下更改应用程序行为的模式。

Java Agent 与主应用程序同时执行,通过 -javaagent 选项加载。

让我们探索编写 Java Agent 所需的步骤。

步骤 1:编写 Agent 类

Agent 的主入口点是 的 premain 方法

文件名:MyAgent.java

关键组件

premain 方法

这实际上标志着 Agent 的入口点,在主应用程序开始之前运行。它接受两个参数:

  • agentArgs:作为字符串传递给 Agent 的参数。
  • Instrumentation:用于修改或查看类的各种方法接口。

类转换器

使用 instrumentation.addTransformer 注册类加载事件,并可能转换字节码。

步骤 2:定义 Manifest 文件

Java Agent 只能在 manifest 文件中声明其执行起始点。创建一个名为 MANIFEST.MF 的文件,内容如下:

Premain-Class:确定 premain 方法的类。

步骤 3:编译和打包 Agent

创建 Agent 类和 manifest 文件后,编译程序并将其打包成 JAR 文件

1. 编译 Agent 类

2. 将 Agent 打包成 JAR

步骤 4:编写目标应用程序

要测试 Agent,请创建一个简单的 Java 应用程序然后引入它。将以下代码保存为 TargetApp.java:

步骤 5:使用 Agent 运行应用程序

输出

 
Agent has been initialized!
Agent arguments: someArgument
Class loaded: jdk/internal/vm/PostVMInitHook
Class loaded: jdk/internal/vm/PostVMInitHook$2
Class loaded: jdk/internal/util/EnvUtils
Class loaded: jdk/internal/vm/PostVMInitHook$1
Class loaded: sun/launcher/LauncherHelper
Class loaded: java/nio/charset/CharsetDecoder
Class loaded: sun/nio/cs/ArrayDecoder
Class loaded: sun/nio/cs/SingleByte$Decoder
Class loaded: sun/nio/cs/MS1252$Holder
Class loaded: java/lang/StringCoding
Class loaded: java/util/concurrent/ConcurrentHashMap$ForwardingNode
Class loaded: TargetApp
Class loaded: jdk/internal/misc/MethodFinder
Class loaded: jdk/internal/misc/PreviewFeatures
Target application is running!
Class loaded: java/lang/Shutdown
Class loaded: java/lang/Shutdown$Lock   

Java Agent 如何工作?

Java Agent 基于事件拦截工作,特别是类加载事件。Instrumentation 接口允许您:

  • 检查类:记录 JVM 加载的类的名称。
  • 转换类:在类被 JVM Java 虚拟机调用之前进行一个级别的转换(一种更高级的技术)。

Agent 的 addTransformer 方法确保系统中加载的任何类都提供回调机会,以便在处理过程中对其进行检查或修改。

结论

Java Agent 是在运行时观察、分析和修改应用程序的强大手段,而无需对其源代码进行任何更改。Agent 利用 java.lang.instrument 包,允许开发人员介入类加载过程,对其进行转换,并在运行时添加其他行为。

这可能是为了展示本指南在构建主要 Agent 并将其与目标应用程序一起使用的灵活性。掌握了这些技能后,开发人员可以进一步利用字节码插桩等技术来创建更有效的工具来分析故障和性能问题,并提高应用程序的有效性。


下一主题登录表单 Java