目次
Java エージェント テクノロジの概要
Java エージェントの機能紹介
ホームページ Java &#&チュートリアル Javaエージェントの使用方法

Javaエージェントの使用方法

May 22, 2023 pm 08:52 PM
java agent

Java エージェント テクノロジの概要

Java エージェントは、文字通り Java エージェントと訳され、Java プローブ テクノロジとも呼ばれます。

Java エージェント このテクノロジーは JDK1.5 で導入され、実行時に Java バイトコードを動的に変更できます。 Java のクラスは、JVM によって実行されるバイトコードを形成するためにコンパイルされます。JVM は、これらのバイトコードを実行する前にこれらのバイトコードの情報を取得し、バイトコード コンバータを通じてこれらのバイトコードを変更してプロセスを完了します。

Java エージェントは、独立して実行できない jar パッケージであり、ターゲット プログラムに接続された JVM プロセスを通じて動作します。起動時に、ターゲット プログラムの起動パラメータに -javaagent パラメータを追加して、ClassFileTransformer バイトコード コンバータを追加するだけです。これは、main メソッドの前にインターセプタを追加するのと同じです。

Java エージェントの機能紹介

Java エージェントには主に次の機能があります。

  • Java エージェント ロード前に Java バイトコードをインターセプトして変更できます;

  • #Java エージェントは、Jvm の実行中にロードされたバイトコードを変更できます;

  • ## Java エージェントのアプリケーション シナリオ:

Eclipse、IntelliJ IDEA などの IDE のデバッグ機能、
  • ホット デプロイメント機能などJRebel として、
  • # Visual VM、JConsole などのさまざまなパフォーマンス分析ツール、

  • # Skywalking、Pinpoint、などのフルリンク パフォーマンス検出ツールなど;
  • Java エージェントの実装原理
  • Java エージェント
  • の実装原理を理解する前に、Java エージェントについて明確に理解する必要があります。クラスロードメカニズム。 1 つは man メソッドを実行する前に premain で実行する方法、もう 1 つは実行中にプログラムを変更する方法で、JVM の Attach によって実装する必要があります。Attach の実装原理は JVMTI に基づいています。
  • 主にクラスをロードする前にバイトコードをインターセプトして変更します

これらの重要な用語をそれぞれ紹介しましょう:

#JVMTI

JVM ツール インターフェイス

で、ユーザー拡張のために JVM によって公開されるインターフェイスのコレクションです。JVMTI はイベント駆動型で、JVM が特定のロジックを実行するたびにトリガーされます。一部のイベントのコールバック インターフェイスこれらのコールバック インターフェイスを通じて、ユーザーは自分自身を拡張できます

JVMTI は、主流の Java 仮想マシンにデバッガー、プロファイラー、モニター、スレッド アナライザーなどのツールを実装するための統合基盤です。実装されている
  • #JVMTIAgent は、JVMTI によって公開されているいくつかのインターフェイスを使用して、実行したいが通常の状況では実行できないことを実行する動的ライブラリです。通常の動的ライブラリと区別するために、 通常、次のように 1 つ以上の関数を実装します。

    ##Agent_OnLoad
  • Function, if theエージェントは起動時にロードされます。JVM パラメータを通じて設定します。

    Agent_OnAttach

    関数。エージェントが起動時にロードされない場合は、最初にターゲット プロセスにアタッチします。その後、ロード コマンドを対応するターゲット プロセスに送信してロードします。Agent_OnAttach 関数
    • Agent_OnUnload 関数は、ロード プロセス中に呼び出されます。エージェントがアンインストールされるとき、これは

    • #javaagent

      と呼ばれ、機器の JVMTIAgent (Linux での対応する動的ライブラリは libinstrument.so) に依存します。また、個人的なものもあります。
    • JPLISAgent
    • (Java Programming Language Instrumentation Services Agent) という名前で、特に Java 言語で書かれたインストルメンテーション サービスのサポートを提供します

    • instrument
    は Agent_OnLoad を実装し、 Agent_OnAttach には 2 つのメソッドがあり、使用すると、エージェントを起動時にロードすることも、実行時に動的にロードすることもできます。起動時のロードでは、-javaagent:jar パッケージ パスと同様の方法で
  • instrument エージェント

    を間接的にロードすることもできます。実行時の動的ロードは JVM のアタッチ メカニズムに依存しており、エージェント はロードを送信することによってロードされます。

    JVM Attach
  • は、JVM が提供するプロセス間通信機能を指し、これにより、あるプロセスが別のプロセスにコマンドを渡し、スレッドなどの内部操作を実行できるようになります。 dump を実行するには、jstack を実行し、ダンプを実行する必要があるスレッドに pid とその他のパラメータを渡す必要があります。
  • Java Agent case使用します。 print メソッド 実行時間を例に挙げると、これは

    Java Agent
  • によって実現されます。
  • まず、合理化された Maven プロジェクトを構築する必要があります。このプロジェクトでは、プラグイン エージェントの実装用とテスト ターゲット プログラムの実装用の 2 つの Maven サブプロジェクトを構築します。

2 つのプロジェクトが共通の依存関係を持つパッケージを親アプリケーションにインポートします

    <dependencies>
        <dependency>
            <groupId>org.javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.28.0-GA</version>
        </dependency>
    </dependencies>
ログイン後にコピー

最初にビルドしますテスト対象プログラム

// 启动类
public class APPMain {
    public static void main(String[] args) {
        System.out.println("APP 启动!!!");
        AppInit.init();
    }
}
// 模拟的应用初始化的类
public class AppInit {
    public static void init() {
        try {
            System.out.println("APP初始化中...");
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
ログイン後にコピー

然后我们启动程序,测试是否能正常执行,程序正常执行之后,我们开始构建探针程序

探针程序中我们需要编写,改变原有class的Transformer,通过自定义的Transformer类完成输出方法执行时间的功能,

Javaエージェントの使用方法

首先构检Agent程序的入口

public class RunTimeAgent {
    public static void premain(String arg, Instrumentation instrumentation) {
        System.out.println("探针启动!!!");
        System.out.println("探针传入参数:" + arg);
        instrumentation.addTransformer(new RunTimeTransformer());
    }
}
ログイン後にコピー

这里每个类加载的时候都会走这个方法,我们可以通过className进行指定类的拦截,然后借助javassist这个工具,进行对Class的处理,这里的思想和反射类似,但是要比反射功能更加强大,可以动态修改字节码。

javassist是一个开源的分析、编辑和创建Java字节码的类库。

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
public class RunTimeTransformer implements ClassFileTransformer {
    private static final String INJECTED_CLASS = "com.zhj.test.init.AppInit";
    @Override
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
        String realClassName = className.replace("/", ".");
        if (realClassName.equals(INJECTED_CLASS)) {
            System.out.println("拦截到的类名:" + realClassName);
            CtClass ctClass;
            try {
                // 使用javassist,获取字节码类
                ClassPool classPool = ClassPool.getDefault();
                ctClass = classPool.get(realClassName);
                // 得到该类所有的方法实例,也可选择方法,进行增强
                CtMethod[] declaredMethods = ctClass.getDeclaredMethods();
                for (CtMethod method : declaredMethods) {
                    System.out.println(method.getName() + "方法被拦截");
                    method.addLocalVariable("time", CtClass.longType);
                    method.insertBefore("System.out.println(\"---开始执行---\");");
                    method.insertBefore("time = System.currentTimeMillis();");
                    method.insertAfter("System.out.println(\"---结束执行---\");");
                    method.insertAfter("System.out.println(\"运行耗时: \" + (System.currentTimeMillis() - time));");
                }
                return ctClass.toBytecode();
            } catch (Throwable e) { //这里要用Throwable,不要用Exception
                System.out.println(e.getMessage());
                e.printStackTrace();
            }
        }
        return classfileBuffer;
    }
}
ログイン後にコピー

我们需要在Maven中配置,编译打包的插件,这样我们就可以很轻松的借助Maven生成Agent的jar包

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <!-- 指定maven编译的jdk版本。若不指定,maven3默认用jdk 1.5 maven2默认用jdk1.3 -->
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>
            <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>
                            <Menifest-Version>1.0</Menifest-Version>
                            <Premain-Class>com.zhj.agent.RunTimeAgent</Premain-Class>
                            <Can-Redefine-Classes>true</Can-Redefine-Classes>
                            <Can-Retransform-Classes>true</Can-Retransform-Classes>
                        </manifestEntries>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>
ログイン後にコピー

否则我们需要在resources下创建META-INF/MANIFEST.MF文件,文件内容如下,我们可以看出这个与Maven中的配置是一致的,然后通过配置编译器,借助编译器打包成jar包,需指定该文件

Manifest-Version: 1.0
Premain-Class: com.zhj.agent.RunTimeAgent
Can-Redefine-Classes: true
Can-Retransform-Classes: true
ログイン後にコピー

告示文件MANIFEST.MF参数说明:

Manifest-Version

文件版本

Premain-Class

包含 premain 方法的类(类的全路径名)main方法运行前代理

Agent-Class

包含 agentmain 方法的类(类的全路径名)main开始后可以修改类结构

Boot-Class-Path

设置引导类加载器搜索的路径列表。查找类的特定于平台的机制失败后,引导类加载器会搜索这些路径。按列出的顺序搜索路径。列表中的路径由一个或多个空格分开。(可选)

Can-Redefine-Classes true

表示能重定义此代理所需的类,默认值为 false(可选)

Can-Retransform-Classes true

表示能重转换此代理所需的类,默认值为 false (可选)

Can-Set-Native-Method-Prefix true

表示能设置此代理所需的本机方法前缀,默认值为 false(可选)

最后通过Maven生成Agent的jar包,然后修改测试目标程序的启动器,添加JVM参数即可

参数示例:-javaagent:F:\code\myCode\agent-test\runtime-agent\target\runtime-agent-1.0-SNAPSHOT.jar=hello

Javaエージェントの使用方法

最终效果:

Javaエージェントの使用方法

以上がJavaエージェントの使用方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Javaの平方根 Javaの平方根 Aug 30, 2024 pm 04:26 PM

Java の平方根のガイド。ここでは、Java で平方根がどのように機能するかを、例とそのコード実装をそれぞれ示して説明します。

Javaの完全数 Javaの完全数 Aug 30, 2024 pm 04:28 PM

Java における完全数のガイド。ここでは、定義、Java で完全数を確認する方法、コード実装の例について説明します。

Java の乱数ジェネレーター Java の乱数ジェネレーター Aug 30, 2024 pm 04:27 PM

Java の乱数ジェネレーターのガイド。ここでは、Java の関数について例を挙げて説明し、2 つの異なるジェネレーターについて例を挙げて説明します。

ジャワのウェカ ジャワのウェカ Aug 30, 2024 pm 04:28 PM

Java の Weka へのガイド。ここでは、weka java の概要、使い方、プラットフォームの種類、利点について例を交えて説明します。

Javaのアームストロング数 Javaのアームストロング数 Aug 30, 2024 pm 04:26 PM

Java のアームストロング番号に関するガイド。ここでは、Java でのアームストロング数の概要とコードの一部について説明します。

Javaのスミス番号 Javaのスミス番号 Aug 30, 2024 pm 04:28 PM

Java のスミス番号のガイド。ここでは定義、Java でスミス番号を確認する方法について説明します。コード実装の例。

Java Springのインタビューの質問 Java Springのインタビューの質問 Aug 30, 2024 pm 04:29 PM

この記事では、Java Spring の面接で最もよく聞かれる質問とその詳細な回答をまとめました。面接を突破できるように。

Java 8 Stream Foreachから休憩または戻ってきますか? Java 8 Stream Foreachから休憩または戻ってきますか? Feb 07, 2025 pm 12:09 PM

Java 8は、Stream APIを導入し、データ収集を処理する強力で表現力のある方法を提供します。ただし、ストリームを使用する際の一般的な質問は次のとおりです。 従来のループにより、早期の中断やリターンが可能になりますが、StreamのForeachメソッドはこの方法を直接サポートしていません。この記事では、理由を説明し、ストリーム処理システムに早期終了を実装するための代替方法を調査します。 さらに読み取り:JavaストリームAPIの改善 ストリームを理解してください Foreachメソッドは、ストリーム内の各要素で1つの操作を実行する端末操作です。その設計意図はです

See all articles