Java仮想マシン(JVM)とは
Java仮想マシン(JVM:
Java Virtual Machine)は、
Javaバイトコードと呼ばれる中間言語を実行するための仮想的なコンピュータです。JVMは、
Javaプログラムが動作するための基盤となる
ソフトウェアであり、
Javaの大きな特徴である「Write once, run anywhere(一度書けば、どこでも実行できる)」を実現する上で不可欠な要素です。
JVMは、単なる
インタプリタではなく、高度な最適化技術やメモリ管理機能などを備えており、
Javaプログラムの実行効率を高める役割も担っています。具体的には、
スタックベースのアーキテクチャを持ち、命令セットを解釈しながらプログラムを実行します。JVMは
Java実行環境(JRE)の一部として提供され、APIや開発ツールと共に、
Javaアプリケーションの実行をサポートします。
JVMの命令セット
JVMは、
Javaバイトコードとして定義された命令セットに従って動作します。この命令セットは、JVMが理解できる低レベルな命令の集まりであり、プログラムの実行に必要な操作を細かく指定します。命令セットは、ニーモニックという人が理解しやすい記号で表現され、それぞれ特定の操作に対応します。以下に、主な命令とその解説を記載します。
bipush, sipush: 1バイトまたは2バイトの整数値をスタックに積みます。
ldc: 定数プールから4バイトの定数(整数、浮動小数点数、文字列)を
スタックに積みます。
ldc_w: `ldc`よりも大きな定数プールエントリを扱うために使用します。
ldc2_w: 定数プールから8バイトの定数(long、double)を
スタックに積みます。
iconst_m1, iconst_0 ... iconst_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:
スタックの先頭2つの値を交換します。
ローカル変数操作
iload, lload, fload, dload, aload: ローカル変数から値をスタックにロードします。
iload_0 ... iload_3, lload_0 ... lload_3, fload_0 ... fload_3, dload_0 ... dload_3, aload_0 ... aload_3: ローカル変数の特定の位置から値をロードします。
istore, lstore, fstore, dstore, astore: スタックの値をローカル変数に格納します。
istore_0 ... istore_3, lstore_0 ... lstore_3, fstore_0 ... fstore_3, dstore_0 ... dstore_3, astore_0 ... astore_3: ローカル変数の特定の位置に値を格納します。
条件分岐とジャンプ
ifeq, ifnull, iflt, ifle, ifne, ifnonnull, ifgt, ifge: スタックの値が特定条件を満たす場合にジャンプします。
if_icmpeq, if_icmpne, if_icmplt, if_icmpgt, if_icmple, if_icmpge:
スタックの整数値同士を比較し、条件が満たされる場合にジャンプします。
if_acmpeq, if_acmpne: スタックの参照値を比較し、条件が満たされる場合にジャンプします。
goto, goto_w: 指定されたアドレスに無条件ジャンプします。
jsr, jsr_w, ret: サブルーチンを呼び出し、戻ります。
lookupswitch, tableswitch: `switch`文を実装するためのジャンプ命令です。
メソッド呼び出しと復帰
invokevirtual: インスタンスメソッドを呼び出します。
invokespecial: コンストラクタ、プライベートメソッド、スーパークラスのメソッドを呼び出します。
invokestatic: クラスメソッドを呼び出します。
invokeinterface: インターフェースメソッドを呼び出します。
return: メソッドから戻ります(値を返さない)。
ireturn, lreturn, freturn, dreturn, areturn: メソッドから値を返して戻ります。
型変換
checkcast: オブジェクトの型をチェックします。
instanceof: オブジェクトの型をチェックし、結果を
スタックに積みます。
i2l, i2f, i2d, i2b, i2c, i2s: 整数を他の型に変換します。
l2i, l2f, l2d: long型を他の型に変換します。
f2i, f2l, f2d: float型を他の型に変換します。
d2i, d2l, d2f: double型を他の型に変換します。
比較演算
dcmpg, dcmpl: double値を比較します。
fcmpg, fcmpl: float値を比較します。
lcmp: long値を比較します。
算術演算
iinc: 整数変数をインクリメントします。
iadd, ladd, fadd, dadd: 加算を行います。
isub, lsub, fsub, dsub: 減算を行います。
imul, lmul, fmul, dmul: 乗算を行います。
idiv, ldiv, fdiv, ddiv: 除算を行います。
irem, lrem, frem, drem: 剰余演算を行います。
ineg, lneg, fneg, dneg: 符号反転を行います。
論理演算
ishl, lshl: 左シフトを行います。
ishr, lshr: 算術右シフトを行います。
iushr, lushr: 論理右シフトを行います。
iand, land: 論理積を行います。
ior, lor: 論理和を行います。
ixor, lxor: 排他的論理和を行います。
オブジェクト操作
new: オブジェクトを生成します。
putfield, getfield: インスタンスフィールドへのアクセスを行います。
putstatic, getstatic: クラスフィールドへのアクセスを行います。
配列操作
iaload, laload, faload, daload, aaload, baload, caload, saload: 配列要素の値を
スタックにロードします。
iastore, lastore, fastore, dastore, aastore, bastore, castore, sastore: 配列要素に値を格納します。
newarray: 基本型の配列を作成します。
anewarray: 参照型の配列を作成します。
multianewarray: 多次元配列を作成します。
arraylength: 配列の長さを取得します。
その他
athrow: 例外をスローします。
nop: 何もしません。
breakpoint: デバッガー用の命令です。
monitorenter, monitorexit: オブジェクトのモニタをロック/アンロックします。
wide: ロード/ストア系命令や`ret`, `iinc`のインデックスを16ビットに拡張します。
JVMの実装
JVMには、複数の実装が存在します。エンタープライズ向けには、Oracle、
IBM、HPなどが提供する実装があり、デスクトップ環境やサーバ環境で利用されます。また、オープンソースコミュニティによる実装も存在し、
IKVM.NETのように共通言語ランタイム上で動作するJVMや、GNU SmalltalkのVM上に構築されたJVMもあります。
JITコンパイル
初期のJVMは
インタプリタ形式で動作していましたが、実行速度を向上させるため、メソッド実行直前にバイトコードをネイティブコードにコンパイルするJIT (Just-in-Time) コンパイラが導入されました。JITコンパイラは、頻繁に実行されるコードを最適化することで、実行速度を大幅に向上させます。
Oracleの
HotSpot VMは、JITコンパイルを高度化した技術であり、実行回数に基づいてコードを動的に最適化します。
HotSpot VMには、クライアントVMとサーバVMの2種類があり、それぞれ最適化の方針が異なります。
スレッドとガベージコレクション
JVMは、スレッドの実行とメモリ管理も担当します。
グリーンスレッド: Javaで仮想的なスレッドを実装する方式ですが、現在ではあまり使用されていません。
ネイティブスレッド: OSのスレッドライブラリを利用する方式が主流です。
また、JVMには自動メモリ管理機構であるガベージコレクション(GC)が実装されており、不要になったオブジェクトを自動的に回収します。GCには、世代別GCやコピーGC、Mark & Sweepなどのアルゴリズムが使用されます。
まとめ
JVMは、
Javaプログラムを実行するための重要な
ソフトウェアであり、
Javaの可搬性を支える基盤となっています。多様な命令セットや高度な最適化技術、メモリ管理機能によって、
Javaプログラムの効率的な実行を実現しています。
関連項目
Apache Harmony: オープンソースのJava実装
Dalvik仮想マシン: Androidで使用される仮想マシン
HotSpot: OracleのJVM実装
IcedTea: オープンソースの
Java実装
IKVM.NET: .NET上で動作するJVM
Kaffe: オープンソースのJVM
leJOS: LEGO MINDSTORMS用のJVM
SableVM: 研究用のJVM