Java プロセスをトレースする BTrace を試してみる
BTrace について
-
Java プログラムのトレーシングツール
-
Java プログラムの実行状況に応じてプログラムで指定したアクションを実行できる
-
ex.) foo メソッドが呼び出されたらタイムスタンプを出力するなど
-
その他のメリットとしては、jdb で Java のプロセスをデバッグする場合はあらかじめ JVM にデバッグ用のオプションを指定する必要があるが、BTrace ではその必要がない
-
元々 Project Kenai でホスティングされていましたが GitHub に移行した模様
BTrace のビルド
- Gradle を使う場合はインターネットに接続されている環境でビルドする必要があります
ビルドしない
-
ビルド済みのファイルがリリースページで公開されています
-
これを利用するのが良さそうです
-
以下は自分でビルドする場合の手順です
Java の設定
- JDK をインストールし、JAVA_HOME を設定します
$ yum install jdk
$ export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk.x86_64/
ダウンロード
- GitHub の Download ZIP ボタンでダウンロードします
- https://github.com/jbachorik/btrace
展開
$ mkdir -p ~/sfw/BTrace
$ mv btrace-master.zip ~/sfw/BTrace
$ cd ~/sfw/BTrace
$ unzip -q btrace-master.zip
プロキシーの設定
- インターネットの接続にプロキシーサーバを通る必要がある場合はプロキシーの設定を行います
$ mkdir ~/.gradle
$ vi ~/.gradle/gradle.property
systemProp.https.proxyHost=<Proxy Host>
systemProp.https.proxyPort=<Port>
ビルド
$ cd btrace-master
$ ./gradlew build
$ ./gradlew buildDistributions
$ ls build/distributions/
btrace-1.4-20160122.112634.noarch.rpm btrace-bin-1.4-SNAPSHOT.zip
btrace-bin-1.4-SNAPSHOT.tgz btrace_1.4-20160122.112634_all.deb
ビルドしたファイルを別のマシンにインストールする
$ cd build/distributions/
$ scp btrace-bin-1.4-SNAPSHOT.zip <user>@<host>:
$ ssh <user>@<host>
Password: <password>
$ mkdir ~/BTrace
$ mv btrace-bin-1.4-SNAPSHOT.zip ~/BTrace
$ cd ~/BTrace
$ unzip -q btrace-bin-1.4-SNAPSHOT.zip
BTrace を使ってみる
準備
- 環境変数 JAVA_HOME, BTRACE_HOME, PATH を設定する
# export JAVA_HOME=/usr/lib/jvm/java-1.8.0
# export BTRACE_HOME=/root/BTrace
# export PATH=${HOME}/BTrace/bin:${PATH}
トレース対象のプログラムのソースコード
import java.time.*;
class myprog01 {
private String time;
public static void main(String[] args) {
myprog01 app = new myprog01();
app.loop();
}
void loop() {
while(true) {
fun();
}
}
void fun() {
try {
this.time = LocalDateTime.now().toString();
Thread.sleep(1000);
} catch(Exception e) {
e.printStackTrace();
}
}
}
トレースプログラム
# cat trace01.java
import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;
@BTrace
public class trace01 {
@OnMethod(
clazz="/myprog01/",
method="/fun/"
)
public static void m(@Self Object o, @ProbeClassName String probeClass, @ProbeMethodName String probeMethod) {
println(Time.millis() + ": " + probeClass + "::" + probeMethod + "()");
}
}
トレース対象のプログラムの PID
# jps
31367 myprog01
31593 Jps
トレースの実行
# btrace 31367 trace01.java
1453438332344: myprog01::fun()
1453438333345: myprog01::fun()
1453438334345: myprog01::fun()
1453438335345: myprog01::fun()
1453438336345: myprog01::fun()
...
要調査項目
-
クラス名、メソッド名、タイムスタンプは出力できました
-
スタックトレース、引数、インスタンス変数、ローカル変数にアクセスできるかどうか確認する
-
スレッド ID にアクセス可能か
-
オーバーヘッドはどのくらいか
-
安全に BTrace を終了する方法を確認する
-
BTrace によって挿入されたコードはどうなるか