Java仮想マシン

Java仮想マシンは、Javaバイトコードとして定義された命令セットを実行するスタック型の仮想マシン。APIやいくつかのツールとセットでJava実行環境としてリリースされている。この環境を移植することで、さまざまな環境でJavaのプログラムを実行することができる。

1. 命令セット仕様
----------

1.1. ニーモニック表
------------



1.2. オペコード解説
------------

1.2.1. スタック
-----------

bipush、 sipush - byte値、 short値をスタックに積む。
ldc - コンスタントプール内の4バイトの定数の内1バイト以内でエントリ番号を指定できるものをスタックに積む。
ldc_w - エントリ番号が1バイトでは足りないときに使う。
ldc2_w - コンスタントプール内の8バイトの定数をスタックに積む。
iconst_m1、 iconst_0、 iconst_1、 iconst_2、 iconst_3、 iconst_4、 iconst_5 - intの-1、0、1、2、3、4、5をスタックに積む。
lconst_0、 lconst_1 - longの0、1をスタックに積む
fconst_0、 fconst_1、 fconst_2 - floatの0、1、2をスタックに積む
dconst_0、 dconst_1 - doubleの0、1をスタックに積む。
aconst_null - スタックにnullを積む。
pop、 pop2 - スタックから1、2ワード取り除く
dup、 dup2
dup_x1、 dup2_x1
dup_x2、 dup2_x2
swap

1.2.2. 局所変数
-----------

iload、 lload、 fload、 dload、 aload - 局所変数からint値、 long値、 float値、 double値、 参照値を取り出してスタックに積む。
iload_0、 iload_1、 iload_2、 iload_3 - 0、1、2、3番目の局所変数からint値を取り出してスタックに積む。
lload_0、 lload_1、 lload_2、 lload_3 - 0、1、2、3番目の局所変数からlong値を取り出してスタックに積む。
fload_0、 fload_1、 fload_2、 fload_3 - 0、1、2、3番目の局所変数からfloat値を取り出してスタックに積む。
dload_0、 dload_1、 dload_2、 dload_3 - 0、1、2、3番目の局所変数からdouble値を取り出してスタックに積む。
aload_0、 aload_1、 aload_2、 aload_3 - 0、1、2、3番目の局所変数から参照値を取り出してスタックに積む。
istore、 lstore、 fstore、 dstore、 astore - int値、 long値、 float値、 double値、 参照値を局所変数に格納。
istore_0、 istore_1、 istore_2、 istore_3 - int値を0、1、2、3番目の局所変数に格納する。
lstore_0、 lstore_1、 lstore_2、 lstore_3 - long値を0、1、2、3番目の局所変数に格納する。
fstore_0、 fstore_1、 fstore_2、 fstore_3 - float値を0、1、2、3番目の局所変数に格納する。
dstore_0、 dstore_1、 dstore_2、 dstore_3 - double値を0、1、2、3番目の局所変数に格納する。
astore_0、 astore_1、 astore_2、 astore_3 - 参照値を0、1、2、3番目の局所変数に格納する。

1.2.3. 条件付きジャンプ
---------------

ifeq、 ifnull、 iflt、 ifle、 ifne、 ifnonnull、 ifgt、 ifge - スタックの値が0、 null、 0未満、 0以下、 0以外、 null以外、 0より大きい、 0以上の場合に指定の番地に制御を移す。
if_icmpeq、 if_icmpne、 if_icmplt、 if_icmpgt、 if_icmple、 if_icmpge - 2つのint値が等しい、等しくない、＜、＞、≦、≧の場合に指定の番地に制御を移す。
if_acmpeq、 if_acmpne - 2つの参照値が等しい、等しくない場合に指定の番地に制御を移す。

1.2.4. ジャンプ
-----------

goto、 goto_w - それぞれ2バイト形式、4バイト形式でもつ相対番地をこの命令の番地に加えた番地に制御を移す。
jsr、 jsr_w - サブルーチンの先頭に制御を移す。gotoと違い、戻り番地を保存する。戻り番地の値はそれぞれ、制御を移す前の番地+3、制御を移す前の番地+5となる。
ret - サブルーチンから呼び出し元の戻り番地に制御を移す。番地が格納されている局所変数を指定する。
lookupswitch - switch文のcase式の値が不連続である場合に、値を探しながら飛び越し先を探し、飛び越しを行う。
tableswitch - switch文のcase式の値が連続である場合に、表を使って飛び越しを行う。

1.2.5. メソッド呼び出し・復帰
------------------

invokevirtual - インスタンスメソッドを呼び出す。
invokespecial - インスタンス初期化メソッド、プライベートメソッド、スーパークラスのインスタンスメソッドを呼び出す。
invokestatic - クラスメソッドを呼び出す
invokeinterface - インターフェイスメソッドを呼び出す。
return - スタックに値を残さずに、呼び出し元の戻り番地に制御を移す。
ireturn、 lreturn、 freturn、 dreturn、 areturn - スタックに int値、 long値、 float値、 double値を残して、サブルーチンの呼び出し元の戻り番地に制御を移す。

1.2.6. 型キャスト
------------

checkcast - 参照値が指し示すインスタンスの型を確認。
instanceof - スタックから参照値をpopし、それが指定された型と同じであれば1を、異なれば0をスタックに積む。
i2l、 i2f、 i2d、 i2b、 i2c、 i2s - int値をlong値、 float値、 double値、 byte値、 char値、 short値に変換したものをスタックに残す。
l2i、 l2f、 l2d - long値をint値に、 float値に、 double値に変換したものをスタックに残す。
f2i、 f2l、 f2d - float値をint値に、 long値に、 double値に変換したものをスタックに残す。
d2i、 d2l、 d2f - double値をint値に、 long値に、 float値に変換したものをスタックに残す。

1.2.7. 比較演算
-----------

dcmpg、 dcmpl - double同士を比較し、1、0または-1をスタックに残す。「-g」と「-l」の違いはオペランドがNaNだったときの扱いの差。
fcmpg、 fcmpl - float同士を比較する。
lcmp - long同士を比較する。

1.2.8. 算術演算
-----------

iinc - intの値を、符号付き1バイトの直接記述した定数だけ増減する。
iadd、 ladd、 fadd、 dadd - int値、 long値、 float値、 double値 で、スタックから取りだした第一の値に第二の値を加え、スタックに積む。
isub、 lsub、 fsub、 dsub - int値、 long値、 float値、 double値 で、スタックから取りだした第一の値から第二の値を引き、スタックに積む。
imul、 lmul、 fmul、 dmul - int値、 long値、 float値、 double値 で、スタックから取りだした第一の値に第二の値を掛け、スタックに積む。
idiv、 ldiv、 fdiv、 ddiv - int値、 long値、 float値、 double値 で、スタックから取りだした第一の値を第二の値で割った商を、スタックに積む。
irem、 lrem、 frem、 drem - int値、 long値、 float値、 double値 で、スタックから取りだした第一の値を第二の値で割った余りを、スタックに積む。
ineg、 lneg、 fneg、 dneg - int値、 long値、 float値、 double値 で、スタックから取りだした値の符号を反転した値をスタックに積む。

1.2.9. 論理演算
-----------

ishl、 lshl - int値、 long値 を指定ビットだけ左にシフトした値をスタックに残す。
ishr、 lshr - int値、 long値 を指定ビットだけ右に算術シフトした値をスタックに残す。負数はシフト後も負に維持される。
iushr、 lushr - int値、 long を指定ビットだけ右に論理シフトした値をスタックに残す。
iand、 land - int値、 long値 の2オペランドのANDを求め、スタックに残す。
ior、 lor - int値、 long の2オペランドの ORを求め、スタックに残す。
ixor、 lxor - int値、 long の2オペランドのXORを求め、スタックに残す。

1.2.10. オブジェクト
--------------

new - インスタンスの生成
putfield、 getfield - メンバ変数への値の代入、値の取り出し
putstatic、 getstatic - クラス変数への値の代入、値の取り出し

1.2.11. 配列
----------

iaload、 laload、 faload、 daload、 aaload、 baload、 caload、 saload - 配列の指定された位置にあるint値、 long値、 float値、double値、参照値、byteまたはboolean値、char値、 short値をスタックに残す。
iastore、 lastore、 fastore、 dastore、 aastore、 bastore、 castore、 sastore - 配列にint値、 long値、 float値、 double値、 参照値、 byteまたはboolean値、 char値、 short値を格納する。
newarray - 数値や文字の配列を作成し、その参照値をスタックに残す。
anewarray - 参照値の配列を作成し、その参照値をスタックに残す。
multianewarray - 多次元配列を作成し、その参照値をスタックに残す。
arraylength - 配列の長さを求め、スタックに残す。

1.2.12. その他
-----------

athrow - java.lang.Throwableのインスタンスで例外やエラーを発生させる。
nop - 何もしない 。
breakpoint - デバッガがブレークポイントの実装に使える命令。
monitorenter - オブジェクトのモニタをロックする。既に他のスレッドにロックされていれば待たされる。
monitorexit - オブジェクトのモニタをアンロックする。他のスレッドのロック待ちは再度試行される。
wide - ロード／ストア系命令やret、iincのインデックスを16ビットに拡張する。iincでは定数も16ビットに拡張する。

2. 実装系
------

エンタープライズ用としては、オラクル、IBM、HPなどの各社から実装系がリリースされている。OS上でアプリケーションとして動作する形態が一般的である。

Windowsにも標準でJava仮想マシンが実装されていたが、マイクロソフトがサン・マイクロシステムズとの契約に反して自社仕様の拡張機能を付加したため、Windows XP以降のOSではJavaの技術使用ライセンスを失った。

また、オープンソースコミュニティの手によってIKVM.NETという共通言語ランタイム上で動作するJava仮想マシンの実装も進められている。

変わった試みとしてGNU SmalltalkのVM上で構築されたJava仮想マシンが存在する。

picoJava, Jazelle などJava仮想マシンの命令がハードウェア実装されたプロセッサ、すなわちバイトコードを直接実行可能なプロセッサも存在する。

2.1. JITコンパイル
-------------

最初のJava仮想マシンの実装はインタプリタ型であったため、動作速度が他のアプリケーションに比べて遅い場合があった。そのため、メソッドの実行直前にバイトコードをCPUのネイティブコードにコンパイルして実行する形式を、ボーランドや IBMなどがリリースした。サン・マイクロシステムズの実装もJDK 1.1からJITコンパイラを搭載した。

加えて、JDK 1.2から、サン・マイクロシステムズはHotSpotという高速化技術を導入した。HotSpotはJITコンパイラの一種だが、常にJITコンパイルを行うのではなく、実行回数が規定回数を超えたメソッド  のみをJITコンパイルする。これにより、JITコンパイルによる無駄なリソースの消費を防いだり、インタプリタ実行時のプロファイリング情報をJITコンパイル利用できる利点がある。HotSpotには用途別に、クライアントVMと、サーバVMがある。

2.2. スレッド
---------

グリーンスレッド - pthread等、OSが提供するスレッドライブラリを直接使わずJavaで仮想的なスレッドを作り実行する形式。現在はあまり利用されていない。
ネイティブスレッド - OSが提供するスレッドライブラリとJavaスレッドが1x1で対応する形式。

2.3. ガベージコレクション
---------------

世代別GC - ヒープを2つ以上の世代に分割し、それぞれに異なるアルゴリズムを適用する方式。

2.3.1. GCアルゴリズム
---------------

コピーGC
Mark & Sweep
Mostly Concurrent Mark & Sweep
Mark & Compact

3. 脚注
-----

4. 関連項目
-------

動作環境
Apache Harmony
Dalvik仮想マシン
HotSpot
IcedTea
IKVM.NET
Kaffe
leJOS
SableVM

5. 外部リンク
--------

[1]

*カテゴリ:Javaカテゴリ:Java specification requests