Exception tableがついちゃってました
バイトコードを見てみよう
前回のエントリー
id:kya-zinc:20091204
でコンパイラにバグがあったことを知った。
何が違ったのかな、と思い、Javapコマンドでバイトコードを見てみた。
問題の関数のみ抜粋。
バグあり版
public void finally_rec(int); Code: 0: iload_1 1: iconst_0 2: if_icmpge 6 5: return 6: getstatic #26; //Field scala/Predef$.MODULE$:Lscala/Predef$; 9: iload_1 10: invokestatic #32; //Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer; 13: invokevirtual #36; //Method scala/Predef$.println:(Ljava/lang/Object;)V 16: aload_0 17: iload_1 18: iconst_1 19: isub 20: invokevirtual #38; //Method finally_rec:(I)V 23: return 24: astore_2 25: aload_0 26: iload_1 27: iconst_1 28: isub 29: invokevirtual #38; //Method finally_rec:(I)V 32: aload_2 33: athrow Exception table: from to target type 16 23 24 any
バグ解決版
public void finally_rec(int); Code: 0: iload_1 (中略) 33: athrow
違いは、前者にException tableがついていることだけで、あとは同じのようだった。
関連知識
invokevirtual #38; //Method finally_rec:(I)Vが二行あるのは、
正常終了した場合(23のreturnまで)と、
例外が発生した場合(33のathrowまで)に展開されるかららしい。
参考:Javaの場合
http://d.hatena.ne.jp/kmaebashi/20080720
バグあり版で2回実行されていたのは
正常終了ケースで例外が発生したら、例外発生ケースにジャンプしていたからのようだ。