Java仮想マシン
Java仮想マシン (Java virtual machine、Java VM、JVM) は、Javaバイトコードとして定義された命令セットを実行するスタック型の仮想マシン。APIやいくつかのツールとセットでJava実行環境 (JRE) としてリリースされている。この環境を移植することで、さまざまな環境でJavaのプログラムを実行することができる。
命令セット仕様
ニーモニック表
0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 | 0x08 | 0x09 | 0x0a | 0x0b | 0x0c | 0x0d | 0x0e | 0x0f | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x00 | 0x00 nop |
0x01 aconst_null |
0x02 iconst_m1 |
0x03 iconst_0 |
0x04 iconst_1 |
0x05 iconst_2 |
0x06 iconst_3 |
0x07 iconst_4 |
0x08 iconst_5 |
0x09 lconst_0 |
0x0a lconst_1 |
0x0b fconst_0 |
0x0c fconst_1 |
0x0d fconst_2 |
0x0e dconst_0 |
0x0f dconst_1 |
0x10 | 0x10 bipush |
0x11 sipush |
0x12 ldc |
0x13 ldc_w |
0x14 ldc2_w |
0x15 iload |
0x16 lload |
0x17 fload |
0x18 dload |
0x19 aload |
0x1a iload_0 |
0x1b iload_1 |
0x1c iload_2 |
0x1d iload_3 |
0x1e lload_0 |
0x1f lload_1 |
0x20 | 0x20 lload_2 |
0x21 lload_3 |
0x22 fload_0 |
0x23 fload_1 |
0x24 fload_2 |
0x25 fload_3 |
0x26 dload_0 |
0x27 dload_1 |
0x28 dload_2 |
0x29 dload_3 |
0x2a aload_0 |
0x2b aload_1 |
0x2c aload_2 |
0x2d aload_3 |
0x2e iaload |
0x2f laload |
0x30 | 0x30 faload |
0x31 daload |
0x32 aaload |
0x33 baload |
0x34 caload |
0x35 saload |
0x36 istore |
0x37 lstore |
0x38 fstore |
0x39 dstore |
0x3a astore |
0x3b istore_0 |
0x3c istore_1 |
0x3d istore_2 |
0x3e istore_3 |
0x3f lstore_0 |
0x40 | 0x40 lstore_1 |
0x41 lstore_2 |
0x42 lstore_3 |
0x43 fstore_0 |
0x44 fstore_1 |
0x45 fstore_2 |
0x46 fstore_3 |
0x47 dstore_0 |
0x48 dstore_1 |
0x49 dstore_2 |
0x4a dstore_3 |
0x4b astore_0 |
0x4c astore_1 |
0x4d astore_2 |
0x4e astore_3 |
0x4f iastore |
0x50 | 0x50 lastore |
0x51 fastore |
0x52 dastore |
0x53 aastore |
0x54 bastore |
0x55 castore |
0x56 sastore |
0x57 pop |
0x58 pop2 |
0x59 dup |
0x5a dup_x1 |
0x5b dup_x2 |
0x5c dup2 |
0x5d dup2_x1 |
0x5e dup2_x2 |
0x5f swap |
0x60 | 0x60 iadd |
0x61 ladd |
0x62 fadd |
0x63 dadd |
0x64 isub |
0x65 lsub |
0x66 fsub |
0x67 dsub |
0x68 imul |
0x69 lmul |
0x6a fmul |
0x6b dmul |
0x6c idiv |
0x6d ldiv |
0x6e fdiv |
0x6f ddiv |
0x70 | 0x70 irem |
0x71 lrem |
0x72 frem |
0x73 drem |
0x74 ineg |
0x75 lneg |
0x76 fneg |
0x77 dneg |
0x78 ishl |
0x79 lshl |
0x7a ishr |
0x7b lshr |
0x7c iushr |
0x7d lushr |
0x7e iand |
0x7f land |
0x80 | 0x80 ior |
0x81 lor |
0x82 ixor |
0x83 lxor |
0x84 iinc |
0x85 i2l |
0x86 i2f |
0x87 i2d |
0x88 l2i |
0x89 l2f |
0x8a l2d |
0x8b f2i |
0x8c f2l |
0x8d f2d |
0x8e d2i |
0x8f d2l |
0x90 | 0x90 d2f |
0x91 i2b |
0x92 i2c |
0x93 i2s |
0x94 lcmp |
0x95 fcmpl |
0x96 fcmpg |
0x97 dcmpl |
0x98 dcmpg |
0x99 ifeq |
0x9a ifne |
0x9b iflt |
0x9c ifge |
0x9d ifgt |
0x9e ifle |
0x9f if_icmpeq |
0xa0 | 0xa0 if_icmpne |
0xa1 if_icmplt |
0xa2 if_icmpge |
0xa3 if_icmpgt |
0xa4 if_icmple |
0xa5 if_acmpeq |
0xa6 if_acmpne |
0xa7 goto |
0xa8 jsr |
0xa9 ret |
0xaa tableswitch |
0xab lookupswitch |
0xac ireturn |
0xad lreturn |
0xae freturn |
0xaf dreturn |
0xb0 | 0xb0 areturn |
0xb1 return |
0xb2 getstatic |
0xb3 putstatic |
0xb4 getfield |
0xb5 putfield |
0xb6 invokevirtual |
0xb7 invokespecial |
0xb8 invokestatic |
0xb9 invokeinterface |
a | 0xbb new |
0xbc newarray |
0xbd anewarray |
0xbe arraylength |
0xbf athrow |
0xc0 | 0xc0 checkcast |
0xc1 instanceof |
0xc2 monitorenter |
0xc3 monitorexit |
0xc4 wide |
0xc5 multianewarray |
0xc6 ifnull |
0xc7 ifnonnull |
0xc8 goto_w |
0xc9 jsr_w |
0xca breakpoint |
b | c | d | e | f |
0xd0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | f |
0xe0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | f |
0xf0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | 0xfe impdep1 |
0xff impdep2 |
オペコード解説
スタック
- bipush、 sipush - byte値、 short値をスタックに積む。
- ldc - コンスタントプール内の4バイトの定数(int値、float値、java.lang.String)の内1バイト以内でエントリ番号を指定できるものをスタックに積む。
- ldc_w - エントリ番号が1バイトでは足りないときに使う。
- ldc2_w - コンスタントプール内の8バイトの定数(long値、double値)をスタックに積む。
- 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
局所変数
- 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番目の局所変数に格納する。
条件分岐
- 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つの参照値が等しい、等しくない場合に指定の番地に制御を移す。
飛び越し
- goto、 goto_w - 現在のプログラムカウンタにそれぞれ2、4バイト加えた番地に制御を移す。
- jsr、 jsr_w - サブルーチンの先頭に制御を移す。gotoと違い、戻り番地を保存する。戻り番地の値はそれぞれ、制御を移す前の番地+3、制御を移す前の番地+5となる。
- ret - サブルーチンの呼び出し元の戻り番地に制御を移す。番地が格納されている局所変数を指定する。
- lookupswitch - switch文のcase式の値が不連続である場合に、値を探しながら飛び越し先を探し、飛び越しを行う。
- tableswitch - switch文のcase式の値が連続である場合に、(キーがインデクス値、値が飛び越し先番地の)表を使って飛び越しを行う。(高速である)
サブルーチンの呼び出し
- invokevirtual - インスタンスメソッドを呼び出す。
- invokespecial - インスタンス初期化メソッド、プライベートメソッド、スーパークラスのインスタンスメソッドを呼び出す。
- invokestatic - クラスメソッドを呼び出す
- invokeinterface - インターフェイスメソッドを呼び出す。
サブルーチンからの復帰
- return - スタックに返を残さずに、サブルーチンの呼び出し元の戻り番地に制御を移す。
- ireturn、 lreturn、 freturn、 dreturn、 areturn - スタックに int値、 long値、 float値、 double値を残して、サブルーチンの呼び出し元の戻り番地に制御を移す。
型キャスト
- 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値に変換したものをスタックに残す。
比較演算
- dcmpg、 dcmpl - double同士を比較し、1または-1をスタックに残す。
- fcmpg、 fcmpl - float同士を比較し、1または-1をスタックに残す。
- lcmp - long同士を比較し、1または-1をスタックに残す
算術演算
- iinc - intの値を、直接記述した定数分、増減する。定数は符号付き8ビットで、int型のビット数に符号付きで拡張後加算される。
- 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値 の反数を求め、スタックに残す。
論理演算
- 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(ビットごとの排他的論理和)を求め、スタックに残す。
オブジェクト
- new - インスタンスの生成
- putfield、 getfield - メンバ変数への値の代入、値の取り出し
- putstatic、 getstatic - クラス変数への値の代入、値の取り出し
配列
- 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 - 配列の長さを求め、スタックに残す。
その他
- athrow - java.lang.Throwableのインスタンスで例外やエラーを発生させる。
- nop - 何もしない (no operation)。
- breakpoint - デバッガがブレークポイントの実装に使える命令。
- monitorenter - オブジェクトのモニタをロックする。既に他のスレッドにロックされていれば待たされる。
- monitorexit - オブジェクトのモニタをアンロックする。他のスレッドのロック待ちは再度試行される。
- wide - ロード/ストア系命令やret、iincのインデックスを16ビットに拡張する。iincでは定数も16ビットに拡張する。
実装系
エンタープライズ用(デスクトップ用を包含)としては、サン・マイクロシステムズ、IBM、HPなどの各社から実装系がリリースされている。、OS上でアプリケーションとして動作する形態が一般的である。
Windowsにも標準でJava仮想マシンが実装されていたが、マイクロソフトがサン・マイクロシステムズとの契約に反して自社仕様の拡張機能を付加したため、Windows XP以降のOSではJavaの技術使用ライセンスを失った。
また、オープンソースコミュニティの手によってIKVM.NETという共通言語ランタイム上で動作するJava仮想マシンの実装も進められている。
![]() | この節の加筆が望まれています。 |
JITコンパイル
最初のJava仮想マシンの実装(JDK 1.0)はインタプリタ型であったため、動作速度が他のアプリケーションに比べて遅い場合があった。そのため、メソッドの実行直前(Just in Time)にバイトコードをCPUのネイティブコードにコンパイルして実行する形式(JITコンパイラ)を、ボーランドや IBMなどがリリースした。サン・マイクロシステムズの実装もJDK 1.1からJITコンパイラを搭載した。
加えて、JDK 1.2から、サン・マイクロシステムズはHotSpotという高速化技術を導入した。HotSpotはJITコンパイラの一種だが、常にJITコンパイルを行うのではなく、実行回数が規定回数を超えたメソッド (Hotspot) のみをJITコンパイルする。これにより、JITコンパイルによる無駄なリソースの消費を防いだり、インタプリタ実行時のプロファイリング情報をJITコンパイル利用できる利点がある。HotSpotには用途別に、クライアントVM(コンパイルは高速だが生成されるネイティブコードが相対的にあまり最適化されない)と、サーバVM(コンパイルは低速だが生成されるネイティブコードが相対的により最適化される)がある。
スレッド
- グリーンスレッド - pthread等、OSが提供するスレッドライブラリを直接使わずJavaで仮想的なスレッドを作り実行する形式。現在はあまり利用されていない。
- ネイティブスレッド - OSが提供するスレッドライブラリとJavaスレッドが1x1で対応する形式。
- 世代別GC - ヒープを2つ以上の世代に分割し、それぞれに異なるアルゴリズム(およびデータ構造)を適用する方式。
GCアルゴリズム(データ構造)
- コピーGC
- Mark & Sweep
- Mostly Concurrent Mark & Sweep
- Mark & Compact
関連項目
- Kaffe - フリーなJava仮想マシン実装
外部リンク
- Java 仮想マシン仕様(Second Edition) - サン・マイクロシステムズ ISBN 489471356X
- Proposed Changes to the Specification of Method Invocation - サン・マイクロシステムズ
- Draft of the Java VM Specification, Third Edition - Alexander Buckley (blogs.sun.com)
- Java 仮想マシンのダウンロード
- Jasmin - JVMアセンブラ Jasminのホームページ