nekop's blog

OpenShift / JBoss / WildFly / Infinispanの中の人 http://twitter.com/nekop

スタックトレースとソースコードの行番号を照合する

「エラー出力されているので調べてください、利用しているJBossのバージョンはAです」と言って渡されたスタックトレースに含まれている行番号がJBossのバージョンAのソースコードと合致しない、というようなことがごくまれにあります。とても不思議ですね。

というのをわざわざ手動でチェックする刺身たんぽぽ作業に飽きたのでRubyスクリプト書いてみました。

https://github.com/nekop/sandbox/blob/master/junk/verspy.rb

まずは適当なコードでスタックトレースを生成してみます。

mkdir -p src/main/java/com/example/test
cat > src/main/java/com/example/test/Hello.java <<EOF
package com.example.test;

public class Hello {

    Hello() {
        throwException();
    }

    public static void main(String[] args) throws Exception {
        System.out.println("hello world");
        new Hello();
    }

    static void throwException() {
        throw new RuntimeException();
    }
}
EOF
mkdir -p target/classes
javac -d target/classes src/main/java/com/example/test/Hello.java
java -classpath target/classes com.example.test.Hello > stacktrace.log 2>&1

生成されたスタックトレースはこんな感じ。

hello world
Exception in thread "main" java.lang.RuntimeException
	at com.example.test.Hello.throwException(Hello.java:15)
	at com.example.test.Hello.<init>(Hello.java:6)
	at com.example.test.Hello.main(Hello.java:11)

スクリプトは-pオプションに調査対象パッケージ名を、-sに調査対象パッケージのソースツリーのルートを指定します。ソースツリーはファイルパスでもhttpなどのURLでもどちらでもいけます。

スタックトレースはファイル名を引数指定するか、標準入力に流します。

このまま実行すると行が一致している問題の無い状態なので一行だけ出力して終了します。

jruby --1.9 ~/usr/src/sandbox/junk/verspy.rb -p com.example.test -s ./src/main/java/ stacktrace.log 
Done, processed 3 stack trace elements.

テストのためにスタックトレースの行番号を11から12とかに書き換えるとソースとマッチしない疑惑の部分が引用表示されます。

vi stacktrace.log
jruby --1.9 ~/usr/src/sandbox/junk/verspy.rb -p com.example.test -s ./src/main/java/ stacktrace.log 
==== 	at com.example.test.Hello.main(Hello.java:12)
11:         new Hello();
12:     }
13: 
Done, processed 3 stack trace elements.

JRubyで実行しているのは単なる趣味であり、ふつうのCRubyでも動作するはずです。