2017年11月8日水曜日

Byteman traceln()やtraceStack()を標準出力ではなくファイルに出力する

JavaプロセスをWindowsサービスとして稼働したり、バックグラウンド起動してターミナルは終了した場合に、Byteman の トレース関数(traceln()やtraceStack())の出力先となる標準出力が無くデバッグが困難となるケースがあります。

このようなケースでは、以下のように traceOpen()でトレース出力先をファイルに向けることで対処できます。

----- sample.btm -----
# トレースを別ファイルに出力
RULE outFile
CLASS sample.SimpleImpl
METHOD getCount
AT ENTRY
IF TRUE
  DO
  traceOpen("myIdentifier01", "C:\dev\myByteman\myByteman.trc");
  traceln("myIdentifier01","---mytrace---"+new java.util.Date());
  traceStack(null,"myIdentifier01");
  traceClose("myIdentifier01");
ENDRULE
-----

$ cat myByteman.trc

---mytrace---Wed Nov 08 00:06:55 JST 2017
Stack trace for thread main
sample.SimpleImpl.getCount(SimpleImpl.java:-1)
sample.MainClass.execute(MainClass.java:15)
sample.MainClass.main(MainClass.java:7)
---mytrace---Wed Nov 08 00:06:58 JST 2017
Stack trace for thread main
sample.SimpleImpl.getCount(SimpleImpl.java:-1)
sample.MainClass.execute(MainClass.java:15)
sample.MainClass.main(MainClass.java:7)
---mytrace---Wed Nov 08 00:07:01 JST 2017
Stack trace for thread main
sample.SimpleImpl.getCount(SimpleImpl.java:-1)
sample.MainClass.execute(MainClass.java:15)
sample.MainClass.main(MainClass.java:7)
(・・・)
----

public boolean traceOpen(Object identifier, String filename)
identifire はトレース出力先を示す識別子になります。

public void traceStack(String prefix, Object key)
prefix に null を指定すると、“Stack trace for thread <current>\n”がスタックトレースの先頭に表示され、<current> には Thread.currentThread().getName() が代入されます。

2017年5月6日土曜日

WebLogic 12.2.1.2.0 管理対象サーバをリモートOSで起動したところ BEA-141149 となる

■WLS 12.2.1.2.0 にて管理対象サーバをリモートで起動しようとした際、以下のエラーが発生しました。

---
####<2017/04/03, 2:13:20,253 午後 JST> <Critical> <WebLogicServer> <xxxx> <Server-0> <main> <<WLS Kernel>> <> <> <1491196400253> 
<[severity-value: 4] [partition-id: 0] [partition-name: DOMAIN] > 
<BEA-000386> <サーバー・サブシステムに障害が発生しました。理由: A MultiException has 2 exceptions.  They are:
1. weblogic.ldap.EmbeddedLDAPException: Empty initial replica
2. java.lang.IllegalStateException: Unable to perform operation: post construct on weblogic.ldap.PreEmbeddedLDAPService

A MultiException has 2 exceptions.  They are:

1. weblogic.ldap.EmbeddedLDAPException: Empty initial replica
2. java.lang.IllegalStateException: Unable to perform operation: post construct on weblogic.ldap.PreEmbeddedLDAPService

        at org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:391)

        ・・・
-----

■Linux側のOS時刻を合わせることで解消しました。
       
■発生した環境は以下の通り
 管理サーバ:Windows10
 管理対象サーバ: Linux(centOS 7)

以下の操作で発生しました。
1. Windows10 、Linux 双方に WLS 12c をインストール
2. Windows10 側にてWLSドメインを作成。管理サーバ、管理対象サーバ(Server-0)を構成
3. Windows10 側にて WLSドメインを pack -managed=true でパック後、Linux 側で unpack。
4. Windows10 側で管理サーバを起動
5. Linux にて $DOMAIN_HOME/bin/startManagedWebLogic.sh Server-0 で起動するとエラー

管理サーバ側には BEA-141149 が出力されます。
----
<2017/05/06, 12:11:49,316 午前 JST> <Error> <Management> <BEA-141149>
<salt m67t55TnLIR/hoG8KV9hvg==、シグネチャRwbmB0APaH95Hr9Y14INaAjBKNP1wm3Sv5FvS/TaOms=の
管理サーバーへ接続しようとする無効な試みが行われました。
おそらく、秘密鍵が一致していないことが原因です。>
----

■原因は筐体間の時刻に著しいずれがあることでした。以下の ディスカッションの通りです。
<BEA-141149> <An invalid attempt was made to connect to the
https://community.oracle.com/thread/3894372

====
14. Re: <BEA-141149> <An invalid attempt was made to connect to the
 ksunil
Newbie
ksunil 2016/02/17 13:22 (ksunil への返信)
This is now resolved. There was nothing wrong with the scripts.
Apparently, the clocks on these 2 Linux boxes were apart (4 minutes) and that triggers something internally. Suggestion came from Oracle support
====

2017年1月29日日曜日

Bytemanチュートリアル(日本語意訳)
稼働中に Byteman エージェントをあとからインストールする方法は?

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

実行中のプログラムをチェックするために Byteman を利用する際、Byteman エージェントをロードせずに実行していたことに気づくことがあります。例えば JBoss アプリケーションサーバのようなプログラムを長時間稼働中、何か問題だ生じたことがログに出力されていた場合などです。
少なくとも Hotspot、JRockit、OpenJDK JVM で実行してたなら、Byteman を使用するために稼働中のプログラムを再起動する必要はありません。これらのJVM の場合、稼働中のプログラムにByteman エージェントを動的に追加インストールすることができます。

Linux なら bminstall.sh スクリプトを利用します。
-----
> bminstall.sh 13101
>
-----

すべての JVM で、動的なエージェントのロードができるわけではありません。
Linux では、Oracle JVM 、OpenJDK、JRockit が、macOSX では OracleJVM と OpenJDK ならできます。
IBM JVM や Windows 上でのその他 JVM で可能かは不明です。

Windows も bminstall.bat を利用します。(リリース 2.0.1 以降)
2.0.1 以前の場合 Install.main() を必要な引数を指定して実行します。
-----
> java -classpath %BYTEMAN_HOME%\lib\byteman-install.jar org.jboss.byteman.agent.install.Install 13101
>
-----

上記の数値(13101)の箇所には、Byteman エージェントをインストールする JVM のプロセスIDを指定します。
チェックしたい稼働中の Java プログラムのその時点の PID を指定する必要があります。(PIDの確認は $JAVAHOME/bin/jps を使うと便利です。)

また、稼働中のJavaプログラムの main クラス名を指定することもできます。(jar コマンド($java -jar myapp.jar)のように起動した場合は、jar名を指定することもできます。)

bminstall.sh は、稼働中の JBoss アプリケーション・サーバ・インスタンスに Byteman エージェントをインストールするのに非常に便利です。AppMain3 を -javaagent オプションなしで再度実行し、稼働後に Byteman エージェントとルール・スクリプトを読み込ませてみましょう。
-javaagent オプションなしで起動しておきます。
    -----
    > java org.my.AppMain3
    foo
    foo
    bar
    bar
    -----

別のコマンドシェルでエージェントをインストールします。
<Linux>
    -----
    > bminstall.sh -b -Dorg.jboss.byteman.transform.all org.my.AppMain3
    >
    -----

bminstall コマンドはルール・スクリプトのロードはできませんが、エージェント・リスナーを自動的に有効にでき、さらに bmsubmt.sh でルールを送信できます。再度 bmsubmit コマンドで thread.btm ルールを送信すると AppMain3 の動作が途中から変更されたことが確認できます。

Bytemanチュートリアル(日本語意訳)
ルールのアンロード方法

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

bmsubmit.sh でルールをアンロードして、AppMain3 の Thread.start() メソッドをオリジナルの動作に戻すことができます。

    -----
    > bmsubmit.sh -u thread.btm
    uninstall RULE trace thread start

    > bmsubmit.sh
    no rules installed
    -----

-u オプションの後にルール・スクリプト名を指定します。指定したルールスクリプト内のすべてのルールがアンロードされ、メソッドに注入されたコードが削除されます。
AppMain3 が、入力テキストを繰り返すのみの最初の動作に戻りました。

    -----
    . . .
    mumble
    *** start for thread: mumble
    mumble
    grumble
    grumble
    bletch
    bletch
    end
    >
    -----

ルール・スクリプトの注入コードのみ変更したいなら、ルールのアンロード、リロードは必要ありません。ルール・スクリプトを修正して再度 submit すれば、Byteman は既存の注入コードを削除し新しいコードを再注入します。

Bytemanチュートリアル(日本語意訳)
どのルールがロードされコンパイルされたか確認したいんですが?

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

bmsubmit.sh を再度実行するとルールが正常にコンパイルされていることが確認できます。

    -----
    > 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
   
    compiled successfully
    >
    -----

「compiled successfully.」と出力されています。これはルールの型チェックに成功し適用されたことを意味します。

ルールが最初にトリガーされたときに型チェックを行った場合([baz]を含む行をタイプした後)は、
型チェック失敗するとコード注入は実行されずに失敗した詳細が出力されます。
注入されたコードはルールがアンロードされたときのみ削除されます。

Bytemanチュートリアル(日本語意訳)
実行中のプログラムにルールを動的適用する方法は?

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
    -----

Bytemanチュートリアル(日本語意訳)
Byteman を簡単に実行する方法はないの?

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

Linux では、-javaagent オプションをラップした $BYTEMAN_HOME/bin/bmjava.sh を利用できます。java コマンドのように見えますが、 ルール・スクリプトをコマンドラインオプションで渡すと、-javaagent script:<ルールスクリプト> として付与してくれます。また、自動で byteman.jar ファイルを boot:<エージェント> オプションとして付与してくれます。
bmjava.sh を使うと前項のコマンドラインを簡素化することができるのです。-l オプションでロードするスクリプトを渡します。
 
-----
> bmjava.sh -l thread.btm org.my.AppMain2 foo bar baz
-----

Windows には bmjava.bat という同等のスクリプトが用意されています(Byteman 2.0.1 以降)。
こちらも同様にシンプルに実行できます。
 
-----
> bmjava -l thread.btm org.my.AppMain2 foo bar baz
 -----

スクリプト名で実行できるよう以下を path 環境変数に通しておいてください。
<Linux>
exprot path=$path:${BYTEMAN_HOME}/bin

<windows>
set path=%path%;%BYETMAN_HOME%/bin

2017年1月5日木曜日

Bytemanチュートリアル(日本語意訳)
どうやって JVM 上のクラスにコードを注入するの?

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


それでは JVM への操作をいくつか行ってみましょう。
以下のような thread.btm ルールファイルを作成してください。

----- thread.btm -----
RULE trace thread start
CLASS java.lang.Thread
METHOD start()
IF true
DO traceln("*** start for thread: "+ $0.getName())
ENDRULE
-----

このルールは JVM のランタイムクラス java.lang.Thread の start() メソッドに処理を注入しています。String 文字列とともに「+」演算子で貼り付けられたトレースメッセージを出力します。

java.lang.Thread#start() は、ある Thread インスタンスのメソッド呼び出し時に呼ばれるインスタンスメソッドです。特殊変数 $0 はこのターゲットオブジェクト自身を参照するために使います。今回の Thread#start() メソッドは引数がありませんが、ルール適用時に引数を伴って呼ばれるメソッドでであれば、その引数を $1、$2 として参照することができます。

$0 が Thread オブジェクトを参照すると認識され、$0.getName() メソッド呼び出しの際にチェックされ、結果が String 型であることが検証されます。このメソッドが呼ばれると、注入されたコードが作成され、String 定数として追加されます。traceln() メソッドに渡されて標準出力(System.out)に書き込まれます。

AppMain を少し変更した AppMain2 にルールを適用してみましょう。AppMain2 はスレッドを複数生成して System.out.println() するクラスです。

----- AppMain2.java -----
package org.my;

class AppMain2
{
    public static void main(String[] args)
    {
        for (int i = 0; i < args.length; i++) {
            final String arg = args[i];
            Thread thread = new Thread(arg) {
                public void run() {
                System.out.println(arg);
                }
            };
            thread.start();
            try {
                thread.join()
            } catch (Exception e) {
            }
        }
    }
}
-----

AppMain2 実行時に、script:<agent> オプションで thread.btm を参照させます。
ただ今回はこれだけでは不十分です。特別なオプションと引数を指定する必要があります。

 <Linux の場合>

-----
> java -javaagent:${BYTEMAN_HOME}/lib/byteman.jar=script:thread.btm,boot:${BYTEMAN_HOME}/lib/byteman.jar -Dorg.jboss.byteman.transform.all org.my.AppMain2 foo bar baz
-----

<Windows の場合>

-----
> java -javaagent:%BYTEMAN_HOME%\lib\byteman.jar=script:thread.btm,boot:%BYTEMAN_HOME%\lib\byteman.jar -Dorg.jboss.byteman.transform.all org.my.AppMain2 foo bar baz
-----

java.lang.Thread クラスはブートストラップ・クラスローダによってロードされます。(ブートストラップ・クラスローダとは、Java の初期クラスローダです。コア・パッケージなど根幹のクラスををロードします)
ブートストラップ・クラスローダでロードされるクラスに処理を注入する場合、Byteman エージェントクラス自体もブートストラップ・クラスローダにロードさせることが必要です。

この場合、特殊なエージェントオプション "boot:${BYTEMAN_HOME}/lib/byteman.jar" を script:<ルールスクリプト> オプションの後ろに追加します。(セパレータとしてカンマ「,」を付与します。)
これで、Byteman エージェントの jar が、ブートストラップ・クラスローダ用のクラスパスに通ります。

また、java.lang.Thread のように java.lang. に所属するようなクラスについて、Byteman ではこのような JVM を中断してしまうようなものはとても慎重に扱っており、デフォルトではコードを注入しない動作をします。このようなコア・パッケージに所属するクラス、メソッドへの変更がどうしても必要な場合、org.jboss.byteman.transform.all システムプロパティの付与が必要です。

AppMain2 を実行してみると、以下の様な出力が得られます。

-----
> java -javaagent:${BYTEMAN_HOME}/lib/byteman.jar=script:thread.btm,boot:${BYTEMAN_HOME}/lib/byteman.jar -Dorg.jboss.byteman.transform.all org.my.AppMain2 foo bar baz
*** start for thread: foo
foo
*** start for thread: bar
bar
*** start for thread: baz
baz
>
-----

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
>

-----

Bytemanチュートリアル(日本語意訳)
ダウンロードとインストール方法は?

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


Byteman を実行する前に Java 6 以上の JVM をインストールしておいてください。

 『Java SE ダウンロード(OTN Japan)』
 http://www.oracle.com/technetwork/jp/java/javase/downloads/index.html

Byteman チュートリアルの例を実行するには Java ソースコードのコンパイルが必要なため、JDK のフルインストールが必要です(javac コンパイラと Java ツール郡を使うため)。JRE のみのシステム上でも Byteman を動かすことはできます。ただ、Byteman エージェントの動的ロード機能を使う場合は、フル JDK インストールが必要です。(Java 開発者であればもう JDK をインストールしているでしょう。)

Byteman バイナリの最新版は Byteman project のダウンロードベージから入手できます。http://byteman.jboss.org/downloads.html
バイナリ zip (Binary + Docs)をダウンロードし、ローカルマシン上の任意ディレクトリに解凍してください。解凍したディレクトリを参照するよう、BYTEMAN_HOME 環境変数を設定してください。

 ・Linux の例

  export BYTEMAN_HOME=${HOME}/Downloads/byteman-1.6.0
  
     ※ HOME 配下の /Downloads/byteman-1.6.0 に展開した例

 ・Windows の例

   set BYTEMAN_HOME=C:\Downloads\byteman-1.6.0
   
     ※ C:\Downloads\byteman-1.6.0 フォルダに展開した例


 BYTEMAN_HOME に指定したディレクトリには、展開されたもの、すなわち README 並び /sample, /lib, /docs, /contrib, /bin サブディレクトリが含まれるようにします。

Linux に Byteman をインストールした場合、${BYTEMAN_HOME}/bin を path 環境変数に追加してください。Byteman を簡単に利用するためのシェルスクリプトが含まれています。

  export PATH=${PATH}:${BYTEMAN_HOME}/bin

Windows にインストールした場合、上記シェルスクリプトの代わりに java コマンドので実行が必要です。※注 2.0.1 以降では 上記シェルの .bat版が bin ディレクトリ配下に含まれています!
同様に環境変数に %BYTEMAN_HOME%\bin を追加してください。

  set PATH=%PATH%;%BYTEMAN_HOME%\bin


これでインストールは完了です。

2017年1月2日月曜日

Bytemanチュートリアル(日本語意訳)
なぜ Byteman を使ったほうがいいの?

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


Byteman を使用すると、ソースコードの修正や再コンパイルすることなく Java プログラムを操作する事ができます。また、プログラムを再実行せず Java アプリケーションの振る舞いを変更する事ができます。自作アプリケーションのクラスや、String や Thread といった JVM の基本クラスの振る舞いを適切に再定義することもできます。

Byteman の最もシンプルな使用例は、プログラムの処理状況を可視化するようコード内に print 文を挿入することです。public、private、protected フィールド変数やローカル変数を参照/出力することができます。また参照したプログラム内の値を処理するために、さらにアプリケーションのメソッドを呼び出すこともできます。
Byteman では、特殊かつ局所化された変更を行うのでアプリケーションに対するオーバーヘッドは少ししか発生しません。これはタイミング依存のコード、特にマルチスレッド・アプリケーションにて同時並行スレッドで生じる特殊なイベントのデバッグに非常に便利です。また、プログラム停止を伴ってデバッグすることができない、本番稼働中のアプリケーションへオーバーヘッドを生じさせずデバッグや監視することもできます。

Byteman はプログラムの制御フローの変更もできます。アプリケーションやランタイムの状態を変えるよう、アプリケーションもしくは JVM のメソッド呼び出しを注入することができます。
また、「static フィールド(静的変数)や instance フィールド(インスタンス変数)」、メソッドの「引数とローカル変数」、メソッド内で「強制的にリターン(復帰)させたり、例外をスローさせる」といった入れ替えもできます。こちらは通常、テストにてエラー状況をシミュレートするために利用されます。アプリケーション内に計測用のコード(instrumentation code) や不正な振る舞いをさせるダミー class を実装して複雑にせず、怪しい挙動を確認したい的確なポイントに簡単にJavaコードを注入できます。

Byteman で操作する Java アプリケーションは Java 6 以上の JVM で実行するようにしてください。もし、古い Java を使用してコンパイルされたコードであっても、心配の必要はありません。
ただ、Byteman では JDK6上でのみフルサポートされている JVM 関数を採用しています。アプリケーションをどうしても Java 5 で実行する必要がある場合、Byteman のレガシーリリース 1.0.3 を使うこともできます。なお、1.0.3 はこのチュートリアルで紹介する基本機能を提供していますが、Byteman エージェントと Byteman ルールの動的ロードはサポートしていません。(詳細は 1.0.3 のユーザーズガイドを確認してください)

Bytemanチュートリアル(日本語意訳)
はじめに

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



バージョン 24

Andrew Dinn が 2011/09/22 7:41 に作成。
Andrew Dinn が 2016/07/25 3:19 に変更。

■はじめに

この文書は Byteman をどう使えばよいか説明する簡単なチュートリアルです。Byteman のインストール方法と、Byteman を使い、簡単な Java プログラムに副作用(side-effects)を注入する方法を説明します。Bitemanをコマンドラインで実行する説明に注力します(あなたはzipリリースをダウンロードする必要があります)。
チュートリアル・パート2 (*1)では、ユニットテストや統合テストにて、Bytemanを使用して意図した障害を注入する方法を説明します。ant と maven から Biteman を稼働させる方法についてです(注:maven への統合には Bytemanをダウンロードする必要はありません。)。チュートリアル・パート2を行う前に、こちらのチュートリアルで理解を深めておくことをおすすめします。

もし Byteman の使い方についてすべて知りたいなら、Byteman Programmer's Guide を参照してください。Byteman の概要、並び、Byteman の操作方法、注入したい副作用のルール定義の方法について詳細に説明されています。また、Byteman のインストール方法と、Byteman の起動方法の包括的な説明もあります。

このチュートリアルは FAQ 形式で作成されています。Byteman を初めて使用する場合は、例を試しながら最初から最後まで読んだほうがいいでしょう。Byteman をすでに使用していて、ちょっと操作方法を確認したり、特定のQAが知りたいだけなら、リンクからジャンプできます。ただ後者の目的なら、完全に把握するためにその他のセクションもざっと読むと良いでしょう。


  1. なぜ Byteman を使ったほうがいいの? (Why Would I Use Byteman?)
  2. ダウンロードとインストール方法は? (How Do I Download And Install Byteman?)
  3. どうやって Byteman を使ってプログラムを実行するの? (How Do I Run A Program Using Byteman?)
  4. どうやって JVM 上のクラスにコードを注入するの? (How Do I Inject Code Into JVM Classes?)
  5. Byteman を簡単に実行する方法はないの? (Is There A Simpler Way To Run Byteman?)
  6. 実行中のプログラムにルールを動的適用する方法は? (How Do I Load Rules Into A Running Program?)
  7. どのルールがロードされコンパイルされたか確認したいんですが?(How Do I See Which Rules Are Loaded And Compiled)
  8. ルールのアンロード方法 (How Do I Unload Rules?)
  9. 実行中のプログラムに Byteman エージェントをあとからインストールする方法は? (How Do I Install The Agent Into A Running Program?) 
  10. JBoss など J2EEサーバ と Byteman を一緒に起動する方法は? (How Do I Run JBoss AS With Byteman)
  11. ルールが正しいか事前に確認したいのだけれど? (How Do I Know My Rules Are Correct?)
  12. ルールがちゃんと動いているか確認したいんだけれど? (How Do I Tell If My Rules Are Being Run?)
  13. ルールを適用したことによる処理遅延をなくしたいのだけれど? (How Can I Make My Rules Run Fast?)
  14. このチュートリアルのソースのダウンロード場所 (Where Can I Download The Tutorial Sources)