2017年1月3日火曜日

Bytemanチュートリアル(日本語意訳)
どうやって Byteman を使ってプログラムを実行するの?

Byteman (http://byteman.jboss.org/docs.html)のチュートリアルを日本語意訳したものです。


Byteman を使って Java アプリケーションを実行する方法はいくつかあります。
一番簡単なのは java をコマンドラインで実行する際に -javaagent オプションを付与する方法です。
簡単な class を使って Byteman の動きを見てみます。


---- AppMain.java ----- 
package org.my; 

class AppMain { 
  public static void main(String[] args) { 
     for (int i = 0; i < args.length; i++) { 
         System.out.println(args[i]); 
     } 
  } 

----

コンパイルして実行してみます。

----- プロンプト -----
> javac org/my/AppMain.java
> java  org.my.AppMain foo bar baz
foo
bar
baz
>
-----

では、Byteman で main メソッドの入り口と出口にトレースコードを注入してみましょう。

はじめに、Byteman ルールスクリプト・ファイル(rule script file)を作成します。任意のディレクトリに 以下の内容の appmain.btm というファイルを作成します。

----- appmain.btm -----
RULE trace main entry
CLASS AppMain
METHOD main
AT ENTRY
IF true
DO traceln("entering main")
ENDRULE

RULE trace main exit
CLASS AppMain
METHOD main
AT EXIT
IF true
DO traceln("exiting main")
ENDRULE
-----

appmain.btm には、AppMain「CLASS」の main() 「METHOD」にコードを注入する、2つのルール「RULE」が含まれています。1つ目のルールは 「AT ENTRY」、すなわち メソッド(METHOD)の開始時に注入されます。注入されるコードは「IF DO」に記載されたものです。1つ目では Byteman のビルトイン関数の traceln(String)(与えられた String 引数を System.out() で新しい行に出力する)を注入しています。2つ目は「AT EXIT」、つまり main ()メソッドがリターンしたタイミングに注入しています。
どちらのルールも「IF true」と定義されています。(これは「DO」が常に実行されることを意味します。)「IF」には「DO」の内容を処理するかどうか制御するために別の Java の式を書くことができます。

これらの Byteman ルールを適用してアプリケーションを実行する -javaagent オプションは、主要なデスクトップ版/サーバ版の JVM でサポートされています。構文は以下のとおりです。

-----
-javaagent : path_to_agent_jar = agent_option1 , agent_option_2 , . . .
-----

Linux にて、アプリケーションを Byteman で appmain.btm ルールを適用して実行するコマンドは以下のとおりです。

-----
> java -javaagent:${BYTEMAN_HOME}/lib/byteman.jar=script:appmain.btm org.my.AppMain foo bar baz
-----

Windwos の場合は以下の通りです。

-----
> java -javaagent:%BYTEMAN_HOME%\lib\byteman.jar=script:appmain.btm org.my.AppMain foo bar baz
-----

「:」の後ろで Byteman エージェントの jar ファイルの参照場所をJVM に教えます。(${BYTEMAN_HOME}/lib/byteman.jar)Byteman エージェント・オプションとして「=」の後ろに Byteman ルールスクリプトファイルの場所( script:appmain.btm )を指定します。すると Byteman エージェントがこのオプションを参照し、appmain.btm ファイルからルールをロードして注入します。もし複数のルールスクリプトをロードしたい場合「script:file」エージェントオプションをカンマ区切りで指定することができます。

-----
> java -javaagent:${BYTEMAN_HOME}/lib/byteman.jar=script:appmain.btm,script:appmain2.btm org.my.AppMain foo bar baz
-----

Java 実行時のコマンドラインで -javaagent オプションを指定すると、JVM が起動時してアプリケーションが実行される前に、Byteman エージェントが開始されます。Byteman エージェントによりルールが読み込まれ、AppMain クラスの main()メソッドが呼ばれる前に副作用が注入されます。結果、以下の出力になります。

-----
> java -javaagent:${BYTEMAN_HOME}/lib/byteman.jar=script:appmain.btm org.my.AppMain foo bar baz
entering main
foo
bar
baz
exiting main
>

-----