実際にdexdumpを用いて.dexファイルを逆アセンブルしてみた(図7注8)。図7では独自に作成したアプリケーション・プログラム「uiTest」の「onCreate」メソッドの冒頭部分を示した。「move-object」という命令が4個続いている。バイト・コードを見ると,いずれも「07」というコードで始まり,続くバイトの上位と下位をそれぞれ引数に割り当てている。例えば「40」に対応する逆アセンブル結果はv0,v4となり,「51」であればv1,v5といった具合だ。おそらくはv0,v1などがレジスタで,4ビットでレジスタ番号を表しているのだろう。つまりレジスタは16個まで存在できることになる。

注8) Androidのアプリケーション・プログラムは「.apk」というパッケージ形式にまとめられているので,dexdumpで直接逆アセンブルすることはできない。ただし,OSが毎回パッケージをひもとくオーバーヘッドを短縮するため,ひもといた結果を「/data/dalvik-cache」と呼ぶディレクトリに格納している。これを対象とした。

図7 バイナリ・コードを逆アセンブルしたところ Java仮想マシンがスタック型を採用しているのに対し,Dalvik VMはレジスタ型の仮想マシンであることが分かる。
図7 バイナリ・コードを逆アセンブルしたところ Java仮想マシンがスタック型を採用しているのに対し,Dalvik VMはレジスタ型の仮想マシンであることが分かる。 (画像のクリックで拡大)

 続くinvoke-super-quickはおそらく親クラスのメソッドを呼び出す命令で,これが「fa02」で表現されている。次の2バイトが動的リンクのためのリンク・テーブルの番号を示しているようだ。const命令は,何らかの定数をレジスタに代入する操作とみられる。またinvoke-virtual-quickはメソッドを呼び出すための命令だろう。

 Dalvik VMの明らかな特徴は,レジスタ型を採用しているところにある。Java仮想マシンはスタック型であり,わざわざ仮想マシンの仕様を変えなければならない理由がありそうだ。ある技術者は,「Javaにはプログラムをロードしたときに,動作の正当性などを検証する『Bytecode verifier』という技術がある。この特許を米Sun Microsystems, Inc.が所有しているので,これに抵触することを避けたためでは」と推測した。また別の技術者は,「レジスタ型の方がコードの最適化を図りやすいのではないか」とみている。ただしこの技術者が現段階の仮想マシンをオープンソースのJava仮想マシン「JamVM」と比べたところ,性能差はあまりなかったという。「レジスタ型の仮想マシンとして,あまりチューニングは進んでいないのではないか」と分析している。

 またレジスタ型を採用すると,ARM926などで提供されるJavaプログラムの高速化機構「Jazelle DBX」が利用できなくなる。ただし「今後新たに登場するARM11アーキテクチャでは,Jazelle DBXは使われなくなるので問題はないだろう」という声があった。

 以上の逆アセンブルの結果だけから,仮想マシンの命令体系の全体像を把握することは難しい。ソース・コードや仮想マシンの仕様公開を待ちたいところだ。

―― 次回へ続く ――