Java(DoJa)で例外が発生した行番号が分からない件
PCエンジンエミュレータの移植の作業は大体終わったのですが、
(とりあえずJavaに書き直したという意味では)
まだバグが取りきれていません。
エミュレータを動かしてしばらく放置すると例外が起きるようです…
しかし、そのスタックトレースを見ても、ソースコードのどこで例外が起きたのか分からないのです。
どういうことかというのを、ちょっと簡単なテストコードを書いて、
以下で検証したいと思います。
DoJa(iアプリ)で例外を発生させてみる
DoJa SDK 5.1とEclipse3.1の環境で、以下のようなコードを実行してみます。
package test; import com.nttdocomo.ui.IApplication; public class Test extends IApplication { public void start() { try { throw new Exception(); } catch (Exception ex) { ex.printStackTrace(); } } }
すると、以下のスタックトレースが出力されます。
java.lang.Exception at test.Test.start(+7)
この「(+7)」って何者でしょうか。
行番号ではありませんね。
これじゃ、スタックトレースを見ても、どこで例外が発生したかわかりません。
じゃあ、バイトコードを見てみよう
classファイルを、javapで逆アセンブルしてみます。
public class test.Test extends com.nttdocomo.ui.IApplication{ public test.Test(); Code: 0: aload_0 1: invokespecial #9; //Method com/nttdocomo/ui/IApplication."":()V 4: return public void start(); Code: 0: new #16; //class java/lang/Exception 3: dup 4: invokespecial #17; //Method java/lang/Exception." ":()V 7: athrow 8: astore_1 9: aload_1 10: invokevirtual #20; //Method java/lang/Exception.printStackTrace:()V 13: return Exception table: from to target type 0 8 8 Class java/lang/Exception }
例外を投げているのは、athrowという命令です。
startメソッドのアドレス7です。
これは、スタックトレースに表示される数値と一致するようです。
つまり、DoJaで作ったアプリを実行したときのスタックトレースの番号は、
行番号ではなく、例外が発生したバイトコードのアドレスを表しているようです。
PC用のJava(J2SDK)でも例外を発生させてみる
PC用のJavaでも同じようなことをやってみます。
class Test { public static void main(String[] args) { try { throw new Exception(); } catch (Exception ex) { ex.printStackTrace(); } } }
実行結果は、以下のスタックトレースが出力されます。
java.lang.Exception at Test.main(Test.java:5)
どうしてこうなった!
なぜ、DoJaでは行番号ではなく、バイトコードのアドレスになってしまうのでしょうか。
バイトコードのアドレスなんかを表示してもらっても、正直こまります。
ウェブで調べると、スタックトレースに行番号が表示されない場合、
以上の原因があるらしいことがわかりました。
しかし、Eclipseの設定を見ても、デバッグ情報は生成するようになっています。
最適化の設定項目は見当たりませんでしたが…
携帯の場合、JITが無いのでそれは関係なさそうです。
なぜ、DoJaはスタックトレースで行番号が出ないのでしょうか。
デバッグのときに非常にこまるのですが。
ウェブで調べても同じようなことで困っている人は居ないのですが。
私のやり方がおかしいのでしょうか。
それとも、誰もそんなこと気にしないのでしょうか。