Byteman (http://byteman.jboss.org/docs.html)のチュートリアルを日本語意訳したものです。
長時間動くプログラムの場合、プログラム実行後にルールをロードしたり、ルールの再ロードをしたいことがあります。これらは Byteman にエージェント・リスナーを起動されば可能になります。エージェント・リスナーはルールのロード状況の確認もできます。
AppMain3 を使って、リスナーの動作を確認しましょう。
----- AppMain3.java -----
package org.my;
import java.io.DataInputStream;
class AppMain3 {
public static void main(String[] args) {
try {
DataInputStream in = new DataInputStream(System.in);
String next = in.readLine();
while (next != null && next.length() > 0 && !next.contains("end")) {
final String arg = next;
Thread thread = new Thread(arg) {
public void run() {
System.out.println(arg);
}
};
thread.start();
try {
thread.join();
} catch (Exception e){ }
next = in.readLine();
}
} catch (Exception e) {}
}
}
-----
AppMain3 は入力されたテキストをそのまま出力します。"end" 文字列、または EOF が入力されると止まります。Byteman エージェント・リスナーと一緒に AppMain3 を起動すると、AppMain3 の読み込み待機中にルールのロード/アンロードができます。またプログラムに解析され注入されたルールの型チェックや実行された状態チェックもできます。
エージェント・リスナーを有効にするには、エージェント・オプション「listener:true」を使います。
<Linux>
-----
$ java -javaagent:${BYTEMAN_HOME}/lib/byteman.jar=listener:true,boot:${BYTEMAN_HOME}/lib/byteman.jar -Dorg.jboss.byteman.transform.all org.my.AppMain3
-----
<Windows>
-----
> java -javaagent:%BYTEMAN_HOME%\lib\byteman.jar=listener:true,boot:%BYTEMAN_HOME%\lib\byteman.jar -Dorg.jboss.byteman.transform.all org.my.AppMain3
-----
エージェント・リスナーは通信口(サーバー・ソケット)を開いてコマンド入力を待ちます。エージェント・オプションにルールスクリプトが指定しなかったので、まずは入力内容が繰り返されるのみです(★)。
----- 実行例 ---
> java -javaagent:${BYTEMAN_HOME}/lib/byteman.jar=listener:true,boot:${BYTEMAN_HOME}/lib/byteman.jar -Dorg.jboss.byteman.transform.all org.my.AppMain3
foo
foo --★
bar
bar --★
-----
<Linux>
エージェント・リスナーに処理させる際は bmsubmit.sh を使います。bmsubmit.sh を引数なしで実行すると、インストールされているルールをすべて表示します。
-----
> bmsubmit.sh
no rules installed
>
(※現在、ルール未インストール)
-----
※ bmsubmit.sh は別シェルを立ち上げ実行してください。また、AppMain3 は先に起動すして、 bmsubmit.sh と Byteman エージェントがサーバーソケットを経由して対話できるようしておきます。
<Windows>
bmsubmit.bat を実行します。(Byteman リリース 2.0.1 以降)
-----
> bmsubmit
no rules installed
>
(※現在、ルール未インストール)
-----
(2.0.1 以前のリリースは、リスナーにコマンドを送信するために Java コマンドで Submit クラスを呼び出す必要があります。)
-----
> java -classpath %BYTEMAN_HOME%\lib\byteman-submit.jar org.jboss.byteman.agent.submit.Submit
no rules installed
>
-----
次に bmsubmit.sh を使って実行中のプログラムにルール・スクリプトをロードします。
<Linux>
-----
> bmsubmit.sh -l thread.btm
install rule trace thread start
>
(※ルール・スクリプト trace がインストールされました。)
-----
<Windows>
bmsubmit.bat を使います。
(リリース 2.0.1 以前は、Submitクラスに -l 引数を付与して実行します。
-----
> java -classpath %BYTEMAN_HOME%\lib\byteman-submit.jar org.jboss.byteman.agent.submit.Submit -l thread.btm
install rule trace thread start
>
(※ルール・スクリプト trace がインストールされました。)
-----
インストールされたルールのステータスを再確認すれば、ルールがロードされ解析されて Thread.start() メソッドに注入されていることが確認できます。もしルールの完全な解析に失敗した場合は、注入が阻止されたことと詳細を含む解析エラーが出力されます。
-----解析エラー-----
> bmsubmit.sh
# File thread.btm line 4
RULE trace thread start
CLASS java.lang.Thread
METHOD start()
AT ENTRY
IF true
DO traceln("*** start for thread: "+ $0.getName())
ENDRULE
Transformed in:
loader: sun.misc.Launcher$AppClassLoader@5acac268
trigger method: java.lang.Thread.start() void
>
-----
実行中のAppMain3で入力を進めるとルールが実行されたことが確認できます。
-----
. . .
bar
bar
baz
*** start for thread: baz
baz
mumble
*** start for thread: mumble
mumble
-----