モジュール java.instrument

パッケージjava.lang.instrument


パッケージjava.lang.instrument
Javaプログラミング言語エージェントが、Java Virtual Machine (JVM)で実行されているプログラムをインストゥルメントできるサービスを提供します。 インストゥルメンテーションのメカニズムは、メソッドのバイトコードの変更です。

エージェントを構成するクラス・ファイルは、実行可能JAR内のアプリケーションとともに、または「エージェントJAR」という個別のJARファイルとして、JARファイルにパッケージ化されます。 JARファイルのメイン・マニフェスト内の属性は、JARファイル内のクラス・ファイルの1つを「エージェント・クラス」として識別します。 エージェント・クラスは、JVMがエージェントをstartに起動する特別なメソッドを定義します。

実行可能JAR内のアプリケーションとともにパッケージ化されたエージェントは、JVMの統計時に起動されます。 エージェントJARファイルにパッケージ化されているエージェントは、コマンドライン・オプションを介してJVMの起動時に、または実装がサポートしている場所で、実行中のJVMで起動できます。

エージェントは、ロード時に任意の方法でクラスを変換したり、モジュールを変換したり、すでにロードされているクラスのメソッドのバイトコードを変換できます。 エージェントのデプロイ、アプリケーションとエージェントをパッケージ化するアプリケーションのデプロイ、または実行中のアプリケーションにエージェントをロードするツールの使用を行う開発者または管理者は、エージェントJARファイルの内容や構造を含む各エージェントの信頼性の検証を担当します。

エージェントの起動

実行可能JARファイル内のアプリケーションとともにパッケージ化されたエージェントの起動

「JARファイルの仕様」は、「実行可能なJARファイル」としてパッケージ化されたスタンドアロン・アプリケーションのマニフェスト属性を定義します。 実装が、アプリケーションを実行可能なJARとして起動するメカニズムをサポートしている場合、JARファイルのメイン・マニフェストにLauncher-Agent-Class属性を含めて、アプリケーションにパッケージ化されたJavaエージェント・クラスのバイナリ名を指定できます。 属性が存在する場合、JVMはエージェント・クラスをロードし、そのagentmainメソッドを呼び出して、エージェントを起動します。 このメソッドは、アプリケーションのmainメソッドが呼び出される前に呼び出されます。 agentmainメソッドには、2つの可能なシグネチャのいずれかがあります。 JVMはエージェント・クラスで最初に次のメソッドを呼び出そうとします。

public static void agentmain(String agentArgs, Instrumentation inst)

エージェント・クラスがこのメソッドを定義しない場合、JVMは次のメソッドを呼び出そうとします:

public static void agentmain(String agentArgs)

agentArgsパラメータの値は、常に空の文字列です。 最初のメソッドでは、instパラメータは、エージェントがコードのインストゥルメントに使用できるInstrumentationオブジェクトです。

agentmainメソッドは、エージェントを起動して戻すために必要な初期化を行う必要があります。 エージェントを起動できない場合(たとえば、エージェント・クラスをロードできない場合、エージェント・クラスが適合agentmainメソッドを定義していない場合、またはagentmainメソッドが捕捉されない例外またはエラーをスローした場合)、JVMはアプリケーションのmainメソッドが呼び出される前に中断されます。

コマンドライン・インタフェースからのエージェントの起動

実装でコマンドライン・インタフェースからエージェントを起動する手段が提供されている場合、エージェントJARは次のコマンドライン・オプションを介して指定されます:

-javaagent:<jarpath>[=<options>]
<jarpath>はエージェントのJARファイルへのパス、<options>はエージェントのオプションです。

エージェントJARファイルのメイン・マニフェストには、属性 Premain-Classが含まれている必要があります。 この属性の値は、JARファイル内のエージェント・クラスのバイナリ名です。 JVMは、エージェント・クラスをロードし、そのpremainメソッドを呼び出して、エージェントを起動します。 このメソッドは、アプリケーションのmainメソッドが呼び出される前に呼び出されます。 premainメソッドには2つのシグネチャのうちのいずれかがあります。 JVMはエージェント・クラスで最初に次のメソッドを呼び出そうとします。

public static void premain(String agentArgs, Instrumentation inst)

エージェント・クラスがこのメソッドを定義しない場合、JVMは次のメソッドを呼び出そうとします:

public static void premain(String agentArgs)

エージェントは、agentArgsパラメータ経由でエージェント・オプションが渡されます。 エージェント・オプションは単一の文字列として渡され、追加の解析はエージェント自身によって行われます。 最初のメソッドでは、instパラメータは、エージェントがコードのインストゥルメントに使用できるInstrumentationオブジェクトです。

エージェントを起動できない場合(たとえば、エージェント・クラスをロードできない場合、エージェント・クラスが適合premainメソッドを定義していない場合、または premainメソッドが捕捉されない例外またはエラーをスローした場合)、JVMはアプリケーションのmainメソッドが呼び出される前に中止されます。

実装がコマンド行インタフェースからエージェントを開始する方法を提供する必要はありません。 実行されると、上記で指定された-javaagentオプションがサポートされます。 -javaagentオプションは、同じコマンドラインで複数回使用することができ、複数のエージェントを起動します。 premainメソッドは、エージェントがコマンドラインで指定された順序で呼び出されます。 複数のエージェントが同じ<jarpath>を使用できます。

エージェント・クラスには、実行中のJVM (下記参照)でエージェントを起動するときに使用するagentmainメソッドもあります。 コマンド行オプションを使用してエージェントを開始した場合は、agentmainメソッドが呼び出されません。

実行中のJVMでのエージェントの起動

実装では、実行中のJVM (JVM起動後の意味)でエージェントを起動するメカニズムを提供できます。 この開始方法の詳細は実装固有ですが、通常はアプリケーションがすでに起動しており、そのmainメソッドがすでに起動されています。 実行中のJVMでエージェントの起動が実装でサポートされている場合、次のことが適用されます:

  1. エージェント・クラスは、エージェントJARファイルにパッケージ化する必要があります。 エージェントJARファイルのメイン・マニフェストには、属性Agent-Classが含まれている必要があります。 この属性の値は、JARファイル内のエージェント・クラスのバイナリ名です。

  2. エージェント・クラスは、public static agentmainメソッドを定義する必要があります。

  3. JVMは、実行中のJVMで起動しようとする各エージェントの標準エラー・ストリームに警告を出力します。 エージェントが以前に (JVMの起動時または実行中のJVMで起動時)を起動していた場合は、同じエージェントを2回目以降に起動しようとしたときに警告が出力されるかどうかに固有の実装です。 警告は、実装固有のコマンド行オプションによって無効にできます。

    実装に関するノート: HotSpot VMでは、JVMオプション-XX:+EnableDynamicAgentLoadingを使用して、実行中のJVMにエージェントを動的にロードできるようにオプトインします。 このオプションは、実行中のJVMでエージェントを起動する際の標準エラーに対する警告を抑制します。

JVMは、エージェント・クラスをロードし、その agentmainメソッドを呼び出して、エージェントを起動します。 agentmainメソッドには、2つの可能なシグネチャのいずれかがあります。 JVMはエージェント・クラスで最初に次のメソッドを呼び出そうとします。

public static void agentmain(String agentArgs, Instrumentation inst)

エージェント・クラスがこのメソッドを定義しない場合、JVMは次のメソッドを呼び出そうとします:

public static void agentmain(String agentArgs)

エージェントは、agentArgsパラメータ経由でエージェント・オプションが渡されます。 エージェント・オプションは単一の文字列として渡され、追加の解析はエージェント自身によって行われます。 最初のメソッドでは、instパラメータは、エージェントがコードのインストゥルメントに使用できるInstrumentationオブジェクトです。

agentmainメソッドでは、エージェントの開始に必要な必須の初期化を実行するようにしてください。 開始が完了すると、メソッドを返すようにします。 エージェントを開始できない場合(たとえばエージェント・クラスをロードできなかったため、またはエージェント・クラスに適切なagentmainメソッドがないため)、JVMは異常終了します。 agentmainメソッドがキャッチされない例外をスローすると、(トラブルシューティングの目的でJVMによって記録されることがあります)は無視されます。

エージェント・クラスには、コマンドライン・オプションを使用してエージェントを起動するときに使用するpremainメソッドもあります。 premainメソッドは、実行中のJVMでエージェントが起動されるときに起動されません。

エージェント・クラスで利用可能なエージェント・クラスとモジュール/クラスの読み込み

エージェントJARファイルからロードされたクラスは、「システム・クラス・ローダー」によってロードされ、システム・クラス・ローダーの「名前のないモジュール」のメンバーです。 システム・クラス・ローダーは、通常、アプリケーションmainメソッドも含むクラスを定義します。

エージェント・クラスに表示されるクラスは、システム・クラス・ローダーに表示されるクラスであり、最小限には次のものが含まれます:

  • 「ブート層」のモジュールによってエクスポートされるパッケージ内のクラス。 ブート・レイヤーにすべてのプラットフォーム・モジュールが含まれているかどうかは、初期モジュールやアプリケーションの起動方法によって異なります。

  • システム・クラス・ローダー(通常はクラスパス)がその名前のないモジュールのメンバーであると定義できるクラス。

  • エージェントが、ブートストラップ・クラス・ローダーによって定義されて、名前の付いていないモジュールのメンバーとなるように手配するすべてのクラス。

エージェント・クラスがブート・レイヤーにないプラットフォーム(その他)モジュールのクラスにリンクする必要がある場合は、これらのモジュールがブート・レイヤー内にあることを保証する方法でアプリケーションを起動する必要があります。 たとえば、JDKの実装では、--add-modulesコマンドライン・オプションを使用して、起動時に解決するルート・モジュールのセットにモジュールを追加できます。

エージェントがブートストラップ・クラス・ローダー(appendToBootstrapClassLoaderSearchまたは以下に指定されたBoot-Class-Path属性を使用して)によってロードされるようにレンジするサポート・クラスは、ブートストラップ・クラス・ローダーに定義されたクラスにのみリンクする必要があります。 すべてのプラットフォーム・クラスがブート・クラス・ローダーによって定義できるという保証はありません。

カスタム・システム・クラス・ローダーが(getSystemClassLoaderメソッドで指定されたシステム・プロパティjava.system.class.loaderを使用して)で構成されている場合は、appendToSystemClassLoaderSearchで指定されているappendToClassPathForInstrumentationメソッドを定義する必要があります。 つまり、カスタム・システム・クラス・ローダーは、エージェントJARファイルをシステム・クラス・ローダーの検索に追加するためのメカニズムをサポートしなければなりません。

JARファイル・マニフェスト属性

アプリケーションまたはエージェントのJARファイル・マニフェストのメイン・セクションにある次の属性は、Javaエージェントに対して定義されます:

Launcher-Agent-Class
実行可能なJARファイルでアプリケーションを起動するメカニズムが実装でサポートされている場合、この属性が存在する場合は、アプリケーションにパッケージ化されているエージェント・クラスのバイナリ名を指定します。 エージェントは、エージェント・クラスのagentmainメソッドを起動して起動します。 これは、アプリケーションのmainメソッドが呼び出される前に呼び出されます。
Premain-Class
エージェントJARがJVMの起動時に指定されている場合、この属性はJARファイル内のエージェント・クラスのバイナリ名を指定します。 エージェントは、エージェント・クラスのpremainメソッドを起動して起動します。 これは、アプリケーションのmainメソッドが呼び出される前に呼び出されます。 この属性が存在しない場合、JVMは異常終了します。
Agent-Class
JVMの起動後のある時点でエージェントを起動するメカニズムが実装でサポートされている場合、この属性はエージェントJARファイル内のJavaエージェント・クラスのバイナリ名を指定します。 エージェントは、エージェント・クラスのagentmainメソッドを起動して起動します。 この属性は必須です。存在しない場合、エージェントは起動されません。
Boot-Class-Path
ブートストラップ・クラス・ローダーで検索されるパスのリストです。 パスはディレクトリまたはライブラリを表します。多くのプラットフォームでは、通常、JARファイルまたはzipライブラリとして参照されます。 クラスを検索するプラットフォーム固有のメカニズムが失敗すると、これらのパスがブートストラップ・クラス・ローダーで検索されます。 パスはリストの順序で検索されます。 リスト内のパスは1つ以上の空白文字で区切られます。 パスの構文は、階層型URIのパス・コンポーネントの構文になります。 スラッシュ文字(/)で始まると絶対パス、それ以外の場合は相対パスです。 相対パスはエージェントのJARファイルの絶対パスに対して解決されます。 パスが不正または存在しない場合は無視されます。 JVMの起動後のある時点でエージェントが起動されると、JARファイルを表さないパスは無視されます。 この属性はオプションです。
Can-Redefine-Classes
ブール値(trueまたはfalse、大文字小文字は区別しない)。 クラスを再定義する機能がこのエージェントに必要かを表します。 true以外の値はfalseであるとみなされます。 この属性はオプションで、デフォルトは falseです。
Can-Retransform-Classes
ブール値(trueまたはfalse、大文字小文字は区別しない)。 クラスを再変換する機能がこのエージェントに必要かを表します。 true以外の値はfalseであるとみなされます。 この属性はオプションで、デフォルトはfalseです。
Can-Set-Native-Method-Prefix
ブール値(trueまたはfalse、大文字小文字は区別しない)。 ネイティブ・メソッドの接頭辞を設定する機能がこのエージェントに必要かを表します。 true以外の値はfalseであるとみなされます。 この属性はオプションで、デフォルトはfalseです。

エージェントJARファイルでは、マニフェスト内にPremain-Class属性と Agent-Class属性の両方が存在することがあります。 -javaagentオプションを使用してエージェントをコマンドラインで起動すると、 Premain-Class属性でエージェント・クラスのバイナリ名が指定され、 Agent-Class属性は無視されます。 同様に、JVMの起動後のある時点でエージェントが起動された場合、Agent-Class属性は、エージェント・クラス(Premain-Class属性の値は無視されます)のバイナリ名を指定します。

モジュール内でコードを計測

ブートストラップ・クラス・ローダーの検索パスにサポート・クラスをデプロイするエージェント、またはメイン・エージェント・クラスをロードするクラス・ローダーの検索パスとして、Java仮想マシンは、変換されたクラスのモジュールを、両方のクラス・ローダーの名前のないモジュールを読み取るように配置します。

導入されたバージョン:
1.5
  • クラス
    説明
    このクラスは、Instrumentation.redefineClassesメソッドに対するパラメータ・ブロックとして機能します。
    クラス・ファイルのトランスフォーマ。
    入力パラメータが無効な場合にClassFileTransformer.transformの実装によってスローされます。
    このクラスは、Javaプログラミング言語コードを計測するためのサービスを提供します。
    指定されたクラスの1つを変更できない場合、Instrumentation.redefineClassesの実装によってスローされます。
    モジュールを変更できないことを示すためにスローされます。