非対話的デバッガ YouDebug

バグ修正はプログラマの仕事の一つですが、このうちのかなりの時間は問題を再現することに費やされます。
症状からバグの全容が推察できる時もあるのですが、多くの場合には、手元で問題を再現し、更なるデータを集めることによって始めてバグが理解されるからです。しかし、環境に依存する問題などは再現が難しい場合もあります。どうしたらよいでしょうか。


ロギングというのがよく行われる解決・予防策ですが、「デバッガを走らせて変数xの値を教えてくれればいいのに!」と思った事があるのは私だけではないと思います。ロギングと異なり、デバッガは予めプログラムに障害発生を予期するコードを埋め込んでおく必要はありません。また、呼び出し元のローカル変数をアクセスしたり、任意の式を評価したり、あるいは変数の値を変更することもできてしまいます。当たり前ですが、障害分析ツールとしてはデバッガはずっと強力だからです。


ではなぜユーザーがデバッガを使わないかというと、それがあまりに難しいからです。そこで、この問題を解決するために、YouDebugを開発しました。


YouDebugはデバッガであると同時にデバッガではありません。YouDebugは、Java Platform Debug Architecture上に作られているので、他のプロセスにアタッチしたり、変数を参照したりブレークポイントを設定したりと、デバッガができる全ての事ができます。そういった意味では、YouDebugはデバッガです。


しかし、YouDebugには対話性がなく、ソースコードも必要ありません。プログラマGUIとマウスを使って駆動するかわりに、YouDebugはDSLライクなGroovyスクリプトを使って駆動されます。これによって、プログラムに関する知識を持ちスクリプトを書く人と、プログラムに関する知識を持たずスクリプトを走らせる人との分業が可能になるわけです。また、Groovyを使うことで、スクリプトの記述を簡潔にしつつも、Javaプログラマに違和感なく使ってもらえるようになっていると思います。


例えば、次のプログラムを見てみましょう。


public class SubStringTest {
public static void main(String[] args) {
String s = someLengthComputationOfString();
System.out.println(s.substring(5));
}

private static String someLengthComputationOfString() {
...;
}
}

ユーザーの一人が、このプログラムがStringIndexOutOfRangeExceptionで死んでいると報告してきました:


Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: -1
at java.lang.String.substring(String.java:1949)
at java.lang.String.substring(String.java:1916)
at com.acme.SubStringTest.main(SubStringTest.java:7)

s.substring(5)が動いていないんだなという事はわかりますが、では変数sは何を指しているのでしょうか?これを調べるために、7行目にブレークポイントをセットしてsを表示しましょう。


breakpoint("com.acme.SubStringTest",7) {
println "s="+s;
}

ユーザーは、まずプログラムを次のように走らせます


$ java -agentlib:jdwp=transport=dt_socket,server=y,address=5005 com.acme.SubStringTest
Listening for transport dt_socket at address: 5005

次に、YouDebugを次のように走らせます。YouDebugは対象のプロセスにアタッチし、sの値が表示されます。


$ java -jar youdebug.jar -socket 5005 SubStringMonitor.ydb
s=test


YouDebugの機能の詳細についてはユーザーガイドを参照してください。ダウンロードはこちらソースコードはこちらです。

追記

http://d.hatena.ne.jp/masanobuimai/20091109#1257769475 でご指摘頂いたバグを修正して1.2を公開しました。若干の非互換の変更も含まれています。上記のダウンロードリンクは1.2をダウンロードします。