[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[jfriends-ml 10312] Re: Joshua Bloch さん と歓談会の様子



(株)ネットジーンの村山です.

>   Gafterさんから出題された Another Quiz の写真ですが、
> ぼやけて判別不可能でした。解説をお願いできますか? > 村山さん

問題が次の通り.
----------
class Main{
  public static void main( String [] args ){
    int [][] a = null;
    a[3][2] = 7;
  }
}

をコンパイルすると,どんなバイトコードが生成されるか.
----------

解答は,次のようになります.
#これはJDKさえあれば,javap -cで誰にでも作れます.
----------
aconst_null
astore_0
aload_0
iconst_3
aaload
iconst_2
bipush 7
iastore 
return
----------
このコードはコンパイルはされるものの,実行時に"aaload"の
時点でNullPointerExceptionが発生するはずです.
#ちなみにbipushのみ2バイト命令で,あとは全て1バイト命令の
#はず.伊達に「バイトコード」と呼ばれてるわけじゃないんですね.

簡単な解説を加えると
----------
aconst_null // オペランドスタックにnull参照をプッシュ
astore_0    // ローカル変数0にストア("a"に代入)

aload_0     // ローカル変数0をロードし,オペランドスタックにプッシュ
iconst_3    // 一次元目のインデックスとして定数3をプッシュ
aaload      // 配列より2次元目の配列インスタンスへの参照をロード
            // 実行時はこの時点でNullPointerExceptionとなるはず.

iconst_2    // 2次元目のインデックスとして定数2をプッシュ
bipush 7    // 代入する数値7をオペランドスタックへプッシュ.
            // iconstは-1(m1)〜5までなので,6以上だと通常は
            // bipushを使うことになる.
iastore     // int配列にストア.

return      // メソッドを終了
----------

短いわりには様々なバイトコードを使用する,良く出来た問題
だと思います.特にひねりもないので,おちついて考えれば正解
を出すのは難しくないはずです.

#それだけに,間違ったのは少しくやしい.多次元配列ということで
#最初にmultianewarrayのことで頭が一杯になったのは失敗だった.
#今までがJava2ME中心だったんで多次元配列はほとんど使わなかった
#ことも一因ではあるが,いずれにせよ間違いには違いない.

この程度の簡単な問題でも,
・ローカル変数名はバイトコードには影響を与えない.
・引数はバイトコードには直接は表れない.(影響はある.)
・staticメソッドにはthisがないので,ローカル変数0から使用可能.
・aconstはnullのみ.
・iconstは-1から5まで
・null参照チェック,配列の境界チェックは実行時に行われる
・多次元配列を直接アクセスする命令はない.(newはある.)
などといった,基本的な知識が試されます.


次回のJavaOneで「バイトコード パズラー」があれば,私も参加して
優勝を目指すんですけどねえ.最大の障害は参加者を集めることって
のが,ちょっと.....


あと,javacは普通は上のようなコードを出力するわけですが,
多分次のようなコードでも,無駄な部分が多いもののJavaVM仕様
には準拠している,正しいコードになると思います.

----------
aconst_null
dup
astore_1
bipush 3
aaload
sipush 7
bipush 2
swap
iastore 
return
----------