2015年11月16日月曜日

ASMのドキュメントを読む(Core API - Methods - Structure)

Javaバイトコード操作のためのライブラリであるASMのガイドのメモの第1弾。
最新版はバージョン5系だが、ガイドは4のものしかない。
http://download.forge.objectweb.org/asm/asm4-guide.pdf

今回はASMまでは言及せずに、JVMの実行モデルについての概念の整理。
  • 各スレッドは実行スタックを持っている(ヒープはスレッドが共有する)
  • 実行スタックには複数のフレームから成る(フレーム1つが、1回のメソッド呼び出しに相当する)
  • フレームはローカル変数部とオペランドスタックから成る(ローカル変数にはインデックスが付いたリスト、オペランドスタックはバイトコード命令のためのスタックである。
  • ちょっと複雑だが、実行スタックの中にオペランドスタックが入っていることになる。
  • バイトコード命令は、opcodeとopcodeごとに決まった数の引数から成る(opcodeは命令の内容を識別するコードで1バイトで表現される。だから「バイトコード」と呼ぶ。)
  • オペランドスタックにはバイトコード命令そのものと、そのバイトコード命令で使うデータも格納する(つまりデータの格納場所としてはローカル変数部とオペランドスタックの2箇所がある)
  • バイトコード命令には、ローカル変数部とオペランドスタックの間でデータを移動させる命令と、オペランドスタックの中だけで操作する命令の2種類がある(あらゆるメソッドが1フレームという単純なルールで表現できるのはちょっと不思議な感じがする)
Javaはオブジェクト指向言語なので、メソッド呼び出し=メッセージ・パッシングである。あるインスタンスメソッドを呼び出す場合、ローカル変数部にはthisと引数が格納される。実際は、ローカル変数はthisのインスタンスはヒープに存在してローカル変数部にはポインタが入っているだけ。longやdouble型の値は、2スロット分を使って格納する(つまり1スロットは4バイト?)。

ASMのガイドにはいろんな例が載っている。例えばpkg.Beanクラスのfというint型フィールドのgetterは以下のようになる。
ALOAD 0・・・ローカル変数部に格納されているthisをオペランドスタックに積む。
GETFIELD pkg/Bean f I・・・pkg.Beanクラスのオブジェクトのfというフィールドのint型の値を取得してオペランドスタックに積む。thisはpopされる。
IRETURN・・・オペランドスタック上のint型の値をpopしてメソッドの戻り値として返す。

fという名前は定数プールから名前解決される。ここを見るとバイトコード命令の実行前後でオペランドスタックの状態がどのように遷移するかがわかりやすい。

次回からASMでバイトコードを扱う方法に入っていく。

0 件のコメント:

コメントを投稿

DockerでMQ環境を作る

DockerHubの ibmcom/mq を使う。ファイルシステムとしてtmpfsは使えないので これ を参考に/mnt/sda1に置き換える。 brew install docker docker-machine docker-machine create --drive...