BTraceを使ってみる
アプリのモジュールに手を入れられない、デバッガも使えない、でも実行情報は取得したい…、というときに便利です。
入手と導入
このあたりからBTraceを入手し、任意のディレクトリへ解凍します。
https://kenai.com/projects/btrace/downloads/directory/releases/current
「BTrace導入ディレクトリ\bin」を環境変数に追加しておくと、コマンドプロンプトから使いやすいですね。
トレース対象のアプリを用意
しょーもないサンプルを用意しました。
public class Plus { private static int plus(int a, int b) { return a + b; } public static void main(String[] args) { for (int i = 0; i < 5000; i++) { System.out.println(plus(i, i)); try { Thread.sleep(1000); } catch (Exception e) { } } } }
トレーススクリプトの記述
Plusアプリのplusメソッドからreturnするタイミングで、クラス名、メソッド名、引数、戻り値を取得してみます。以下のファイルを作成し、BTraceTest.javaという名前で保存します。
import com.sun.btrace.AnyType; import com.sun.btrace.annotations.*; import static com.sun.btrace.BTraceUtils.*; @BTrace public class BTraceTest { @OnMethod( clazz="Plus", // 適用するクラス名。正規表現も使える。正規表現の場合は"/jp\.co\..*/"のように/で囲む。 method="plus", // 適用するメソッド名。正規表現も使える。クラス名と同じ。 location=@Location(Kind.RETURN) // 適用タイミング ) public static void method( AnyType[] args, @ProbeClassName String className, @ProbeMethodName String methodName, @Return int ret ) { String message = ""; message = concat(message, className); message = concat(message, "#"); message = concat(message, methodName); message = concat(message, " ["); message = concat(message, str(args[0])); message = concat(message, ", "); message = concat(message, str(args[1])); message = concat(message, "] return="); message = concat(message, str(ret)); println(message); } }
実行
コマンドプロンプトを開き、まずは普通にアプリを実行します。
> java Plus
続いて、もう一つコマンドプロンプトを開き、jpsコマンドを使ってアプリ(Plus)のプロセスIDを調べます。
> jps 6524 Jps 6408 Plus
6408がアプリのプロセスIDですね。
続いてBTraceを実行します。
> btrace 6408 BTraceTest.java
実行結果はこんな感じです。
: Plus#plus [1025, 1025] return=2050 Plus#plus [1026, 1026] return=2052 Plus#plus [1027, 1027] return=2054 Plus#plus [1028, 1028] return=2056 Plus#plus [1029, 1029] return=2058 :