コンパイル結果をネイティブ・コードにしないということで、特定のOS やハードウエアに依存しない実行環境を提供する方法もあります。この方法を使っているのは、「Java」です。Java には、2 つの側面があります。ひとつはプログラミング言語としてのJava であり、もうひとつはプログラムの実行環境としてのJava です。

 Java は、他のプログラミング言語と同様に、Java の文法で記述されたソースコードをコンパイルしたものを実行します。ただし、コンパイル後に生成されるのは、特定のCPU 用のネイティブ・コードではなく、バイトコードと呼ばれるものです。バイトコードの実行環境をJava 仮想マシン(Java VM = Java Virtual Machine)と呼びます。Java 仮想マシンは、Java バイトコードを逐次ネイティブ・コードに変換しながら実行します。

 たとえば、Windows パソコン用のJava コンパイラとJava 仮想マシンを使った場合は、プログラマが作成したソースコードをコンパイラがバイトコードに変換します。Java 仮想マシンがバイトコードをx86 系CPU 用のネイティブ・コードとWindows 用のAPI 呼び出しに変換し、x86 系CPU とWindows が実際の処理を行います。

 コンパイル後のバイトコードを、実行時にネイティブ・コードに変換するという、回りくどいような手法は、同じバイトコードを異なる実行環境で動作させるための手段です。さまざまな種類のOS やハードウエアに合わせてJava 仮想マシンを用意しておけば、同じバイトコードのアプリケーションがどの環境でも動作します。このようなJava の特徴は「Write once, run anywhere(一度プログラムを書けば、どこでも動作する)」と呼ばれます(図7-6)。

 Windows にはWindows 用のJava 仮想マシンが提供され、Mac にはMac用のJava 仮想マシンが提供されています。OS から見ればJava 仮想マシンは一種のアプリケーションですが、Java アプリケーションから見ればJava 仮想マシンは動作環境 = OS +ハードウエアです。

 ただし、いいことずくめのように見えるJava 仮想マシンにも課題はあります。ひとつは、異なるJava 仮想マシンの間で、完全には互換性がとれていないことです。どのJava 仮想マシンでも、あらゆるバイトコードを動作可能にするのはなかなかむずかしいからです。もうひとつは、実行速度の問題です。実行時にバイトコードをネイティブ・コードに変換するJava のプログラムは、コンパイル結果をネイティブ・コードするC言語のプログラムよりも遅くなります。