モジュール java.instrument

パッケージjava.lang.instrument


パッケージjava.lang.instrument
Javaプログラミング言語エージェントによりJVMで実行中のプログラムを計測するサービスを提供します。 インストゥルメンテーションのメカニズムは、メソッドのバイト・コードの変更です。

エージェントはJARファイルとして配備されます。 JARファイルに含まれるマニフェストの属性は、エージェントを起動するためにロードされるエージェント・クラスを指定します。 エージェントはいくつかの方法で開始できます:

  1. コマンドライン・インタフェースをサポートする実装では、コマンドラインでオプションを指定することでエージェントを起動できます。

  2. インプリメンテーションは、VMの起動後しばらくしてエージェントを起動するメカニズムをサポートします。 たとえば、実行中のアプリケーションにツールを接続して、ツールのエージェントをそのアプリケーションにロードし始められるようなメカニズムを提供できる実装もあります。

  3. エージェントは、実行可能な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の開始後にエージェントを開始できる場合は、次の条件が適用されます。

  1. エージェントJARのマニフェストには、そのメインのmanfiestに属性 Agent-Classが含まれていなければなりません。 この属性の値は、エージェント・クラスの名前です。

  2. エージェント・クラスは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の実装によってスローされます。
    モジュールを変更できないことを示すためにスローされます。