パッケージjava.lang.instrument
エージェントはJARファイルとして配備されます。 JARファイルに含まれるマニフェストの属性は、エージェントを起動するためにロードされるエージェント・クラスを指定します。 エージェントはいくつかの方法で開始できます:
コマンドライン・インタフェースをサポートする実装では、コマンドラインでオプションを指定することでエージェントを起動できます。
インプリメンテーションは、VMの起動後しばらくしてエージェントを起動するメカニズムをサポートします。 たとえば、実行中のアプリケーションにツールを接続して、ツールのエージェントをそのアプリケーションにロードし始められるようなメカニズムを提供できる実装もあります。
エージェントは、実行可能なJARファイルにアプリケーションとともにパッケージ化されていてもよい。
エージェントは、ロード時に任意の方法でクラスを変換したり、モジュールを変換したり、すでにロードされているクラスのメソッドのバイトコードを変換できます。 エージェントのデプロイ、アプリケーションとエージェントをパッケージ化するアプリケーションのデプロイ、または実行中のアプリケーションにエージェントをロードするツールの使用を行う開発者または管理者は、エージェントJARファイルの内容や構造を含む各エージェントの信頼性の検証を担当します。
次に、エージェントを起動する3つの方法について説明します。
コマンドライン・インタフェースからのエージェントの起動
インプリメンテーションがコマンドライン・インタフェースからエージェントを起動する手段を提供する場合、エージェントはコマンドラインに次のオプションを追加することによって開始されます:
-javaagent:<jarpath>[=<options>]
<jarpath>
はエージェントのJARファイルへのパス、<options>
はエージェントのオプションです。
エージェントJARファイルのマニフェストは、そのメイン・マニフェストに属性 Premain-Class
を含まなければなりません。 この属性の値は、エージェント・クラスの名前です。 エージェント・クラスは、基本的にmain
アプリケーション・エントリ・ポイントと同様のpublic static premain
メソッドを実装する必要があります。 Java Virtual Machine (JVM)が初期化された後、premain
メソッドが呼び出され、実際のアプリケーションmain
メソッドが呼び出されます。 premain
メソッドは、起動を続行するために戻る必要があります。
premain
メソッドには2つのシグネチャのうちのいずれかがあります。 JVMはエージェント・クラスで最初に次のメソッドを呼び出そうとします。
public static void premain(String agentArgs, Instrumentation inst)
エージェント・クラスにこのメソッドが実装されていない場合は、次のメソッドを呼び出そうとします。
public static void premain(String agentArgs)
エージェント・クラスは、VM起動(下記参照)の後にエージェントを起動するときに使用するagentmain
メソッドを持つこともできます。 コマンド行オプションを使用してエージェントを開始した場合は、agentmain
メソッドが呼び出されません。
各エージェントは、agentArgs
パラメータ経由でエージェント・オプションが渡されます。 エージェント・オプションは単一の文字列として渡され、追加の解析はエージェント自身によって行われます。
エージェントを(たとえば、エージェント・クラスをロードできないか、エージェント・クラスに適切なpremain
メソッドがないためです)で起動できない場合、JVMは異常終了します。 premain
メソッドが、キャッチされない例外をスローすると、JVMが異常終了します。
実装がコマンド行インタフェースからエージェントを開始する方法を提供する必要はありません。 実行されると、上記で指定された-javaagent
オプションがサポートされます。 -javaagent
オプションは、同じコマンドラインで複数回使用することができ、複数のエージェントを起動します。 premain
メソッドは、エージェントがコマンドラインで指定された順序で呼び出されます。 複数のエージェントが同じ<jarpath>
を使用することがあります。
エージェントpremain
メソッドの実行内容に関するモデリング制約はありません。 作成側スレッドを含め、アプリケーションmain
が実行できることは、すべてpremain
で有効です。
VM起動後のエージェントの起動
実装では、VMの起動後にエージェントを起動するメカニズムが提供される場合があります。 開始する方法の詳細は、実装によって異なりますが、通常はアプリケーションが開始済みで、そのアプリケーションmain
メソッドが呼出し済みです。 VMの開始後にエージェントを開始できる場合は、次の条件が適用されます。
エージェントJARのマニフェストには、そのメインのmanfiestに属性
Agent-Class
が含まれていなければなりません。 この属性の値は、エージェント・クラスの名前です。エージェント・クラスはpublic static
agentmain
メソッドを実装する必要がある。
agentmain
メソッドには、2つの可能なシグネチャのいずれかがあります。 JVMはエージェント・クラスで最初に次のメソッドを呼び出そうとします。
public static void agentmain(String agentArgs, Instrumentation inst)
エージェント・クラスにこのメソッドが実装されていない場合は、次のメソッドを呼び出そうとします。
public static void agentmain(String agentArgs)
エージェント・クラスには、コマンドライン・オプションを使用してエージェントを起動するときに使用するpremain
メソッドもあります。 VMの開始後にエージェントが開始されると、premain
メソッドは呼び出されません。
エージェントは、agentArgs
パラメータ経由でエージェント・オプションが渡されます。 エージェント・オプションは単一の文字列として渡され、追加の解析はエージェント自身によって行われます。
agentmain
メソッドでは、エージェントの開始に必要な必須の初期化を実行するようにしてください。 開始が完了すると、メソッドを返すようにします。 エージェントを開始できない場合(たとえばエージェント・クラスをロードできなかったため、またはエージェント・クラスに適切なagentmain
メソッドがないため)、JVMは異常終了します。 agentmain
メソッドがキャッチされない例外をスローすると、(トラブルシューティングの目的でJVMによって記録されることがあります)は無視されます。
実行可能なJARファイルにエージェントを含める
JARファイル仕様では、「実行可能なJARファイル」としてパッケージ化されたスタンドアロン・アプリケーションのマニフェスト属性が定義されています。 実装が実行可能なJARとしてアプリケーションを起動するメカニズムをサポートする場合、メイン・マニフェストには、アプリケーションmain
メソッドが呼び出される前に開始するエージェントのクラス名を指定するLauncher-Agent-Class
属性が含まれている場合があります。 Java仮想マシンは、エージェント・クラスで次のメソッドを呼び出そうとします:
public static void agentmain(String agentArgs, Instrumentation inst)
エージェント・クラスにこのメソッドが実装されていない場合は、次のメソッドを呼び出そうとします。
public static void agentmain(String agentArgs)
agentArgs
パラメータの値は、常に空の文字列です。
agentmain
メソッドは、エージェントを起動して戻るために必要な初期化を行う必要があります。 たとえば、エージェント・クラスをロードできないなどエージェントを起動できない場合、エージェント・クラスは適合するagentmain
メソッドを定義しません。またはagentmain
メソッドがキャッチされない例外またはエラーをスローすると、JVMは異常終了します。
エージェント・クラスで利用可能なエージェント・クラスとモジュール/クラスの読み込み
エージェントJARファイルからロードされたクラスは、「システム・クラス・ローダー」によってロードされ、システム・クラス・ローダー「名前のないモジュール」のメンバーです。 システム・クラス・ローダーは、通常、アプリケーションmain
メソッドも含むクラスを定義します。
エージェント・クラスに表示されるクラスは、システム・クラス・ローダーに表示されるクラスであり、最小限には次のものが含まれます:
「ブート層」内のモジュールによってエクスポートされたパッケージ内のクラス。 ブート・レイヤーにすべてのプラットフォーム・モジュールが含まれているかどうかは、初期モジュールやアプリケーションの起動方法によって異なります。
システム・クラス・ローダー(通常はクラスパス)がその名前のないモジュールのメンバーであると定義できるクラス。
エージェントが、ブートストラップ・クラス・ローダーによって定義されて、名前の付いていないモジュールのメンバーとなるように手配するすべてのクラス。
エージェント・クラスがブート・レイヤーにないプラットフォーム(その他)モジュールのクラスにリンクする必要がある場合は、これらのモジュールがブート・レイヤー内にあることを保証する方法でアプリケーションを起動する必要があります。 たとえば、JDKの実装では、--add-modules
コマンドライン・オプションを使用して、起動時に解決するルート・モジュールのセットにモジュールを追加できます。
エージェントがブートストラップ・クラス・ローダー(appendToBootstrapClassLoaderSearch
または以下に指定されたBoot-Class-Path
属性を使用して)によってロードされるようにアレンジするサポート・クラスは、ブートストラップ・クラス・ローダーに定義されたクラスにのみリンクする必要があります。 すべてのプラットフォーム・クラスがブート・クラス・ローダーによって定義できるという保証はありません。
カスタム・システム・クラス・ローダーが(getSystemClassLoader
メソッドで指定されたシステム・プロパティjava.system.class.loader
を使用して)に構成されている場合は、appendToSystemClassLoaderSearch
で指定されているappendToClassPathForInstrumentation
メソッドを定義する必要があります。 つまり、カスタム・システム・クラス・ローダーは、エージェントJARファイルをシステム・クラス・ローダーの検索に追加するためのメカニズムをサポートしなければなりません。
マニフェスト属性
エージェントJARファイルには次のマニフェスト属性が定義されています。
Premain-Class
- JVMの起動時にエージェントが指定される場合は、この属性でエージェント・クラスを指定します。 つまり、
premain
メソッドが含まれるクラスです。 JVMの起動時にエージェントが指定される場合は、この属性が必須です。 この属性が存在しない場合、JVMは異常終了します。 ノート: これはクラス名であり、ファイル名やパスではありません。Agent-Class
- VMの開始後にエージェントを開始するメカニズムが実装でサポートされている場合は、この属性でエージェント・クラスを指定します。 つまり、
agentmain
メソッドが含まれるクラスです。 エージェントが起動しない場合、この属性は必須です。 ノート: これはクラス名であり、ファイル名やパスではありません。Launcher-Agent-Class
- 実装が実行可能なJARとしてアプリケーションを起動するメカニズムをサポートしている場合、メインのマニフェストはこの属性を組み込んで、アプリケーション
main
メソッドが呼び出される前に開始するエージェントのクラス名を指定することができます。Boot-Class-Path
- ブートストラップ・クラス・ローダーで検索されるパスのリストです。 パスはディレクトリまたはライブラリを表します。多くのプラットフォームでは、通常、JARファイルまたはzipライブラリとして参照されます。 クラスを検索するプラットフォーム固有のメカニズムが失敗すると、これらのパスがブートストラップ・クラス・ローダーで検索されます。 パスはリストの順序で検索されます。 リスト内のパスは1つ以上の空白文字で区切られます。 パスの構文は、階層型URIのパス・コンポーネントの構文になります。 スラッシュ文字(/)で始まると絶対パス、それ以外の場合は相対パスです。 相対パスはエージェントのJARファイルの絶対パスに対して解決されます。 パスが不正または存在しない場合は無視されます。 VMの開始後にエージェントが開始される場合は、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
属性は無視されます。 同様に、VMの開始後にエージェントが開始される場合は、Agent-Class
属性でエージェント・クラスの名前を指定し、Premain-Class
属性は無視されます。
モジュール内でコードを計測
ブートストラップ・クラス・ローダーの検索パスまたはメイン・エージェント・クラスをロードするクラス・ローダーの検索パスにサポート・クラスをデプロイするエージェントの助けとして、Java仮想マシンは変換されたクラスのモジュールが名前のないモジュールを読み取るように手配します両方のクラス・ローダーの。
- 導入されたバージョン:
- 1.5
-
クラス説明このクラスは、
Instrumentation.redefineClasses
メソッドに対するパラメータ・ブロックとして機能します。クラス・ファイルのトランスフォーマです。入力パラメータが無効な場合にClassFileTransformer.transform
の実装によってスローされます。このクラスは、Javaプログラミング言語コードを計測するためのサービスを提供します。指定されたクラスの1つを変更できない場合、Instrumentation.redefineClasses
の実装によってスローされます。モジュールを変更できないことを示すためにスローされます。