Java の実行形態

Revised: Apr./27th/2008; Since: Dec./23rd/2001

ここでは Java のコンピュータ言語としての特徴をまとめておく。興味が無ければ飛ばしても構わない。但し、後続の章で分からないことがあれば、戻ってくるように勧める。

プログラミング言語の分類

実行形式で分類すると、 Java はインタープリタ型言語である。ただし、純粋なインタープリタ言語ではなく、中間言語方式などと呼ばれる。

機械語 (machine language)
コンピュータの演算/制御装置 (MPU) の動作命令は 2 進数で表される。これを機械語と呼び、一つの動作に対して一つのコードが存在する。同じ動作でも MPU の種類によってコードは異なる。コンピュータが実行可能なのは機械語だけ。機械の動作を直接指示するために、きめ細かい指定が可能であり、機械の機能を最大限に利用できる。
アセンブリ言語 (assembly language)
機械語のコードを一対一対応で、自然言語の単語(ニーモニック)に翻訳したもの。無意味な 2 進数に比べて覚えやすく書き間違いも少ないし、読んで理解しやすい。機械語に翻訳する処理系をアセンブラと呼び、アセンブラで機械語に翻訳することをアセンブル、機械語をアセンブリ言語に逆翻訳することをディスアセンブルと呼ぶ。アセンブルして生成したモジュールを連係編集(LinkEdit。エルケド)して生成した実行ファイルを実行するため、動作速度自体は機械語に遜色はない。実行ファイルは、メイン・メモリにロードされて実行される単位であり、ロード・モジュールと呼ばれる。
コンパイラ型言語 (compiler language)
より人間が理解しやすい構文を持った言語で、高級言語と呼ばれる。マシン固有の機械語に翻訳する処理系(ソフトウェア)をコンパイラと呼ぶ。コンパイラで機械語に翻訳する事をコンパイルと呼び、コンパイラによって生成された機械語のファイルをオブジェクト・コードと呼ぶ。オブジェクト・コードは、ライブラリと呼ばれるモジュール群から必要なモジュールをincludeして、それらを連係編集することで実行ファイルとなる。コンパイラと呼ばれる処理系は、ソースファイルからオブジェクト・コードを生成して、ロード・モジュールに連係編集するところまで一気に処理するのが普通である。マシン固有の機械語の実行ファイルを用意してから実行することになるので、実行速度も機械語/アセンブリ言語に順ずる。C/C++, FORTRAN, COBOL, PL/I など。
インタープリタ型言語 (interpretive language)
プログラムの実行時に、ソースプログラムを逐次、実行可能な形式に変換しながら処理を進める形式の言語。インタープリタ型言語は、実行時にソースプログラムの機械語への翻訳のプロセスが存在するため、コンパイラ型言語にくらべて実行速度が低下する。実行時に翻訳、実行する処理系をインタープリタと呼ぶ。 Shell Script, Perl, LISP, Ruby, JavaScript など。
Java
インタープリタ型言語に分類される。一旦コンパイラでバイトコードと呼ばれる中間言語に変換してから、それを JavaVM (Java Virtual Machine) と呼ばれる処理系でインタープリタ型言語として実行する。バイトコードは JavaVM にとっては機械語であり、 JavaVM がインストールされたOSにとってはアセンブリ言語と同様なので、その解釈/実行は通常のインタープリタによる変換作業よりも高速。
アプリケーションの実行形態
図:アプリケーションの実行形態

メインフレーム全盛期には、HEX Dump(16進ダンプ)を見てニーモニックに翻訳できる人がいて、"walking assembler/disassembler" と呼ばれていた。プログラム全体を、構造化プログラミングという手続きに従ってモジュール化することによって、一部が変更されても、そのモジュールを連係編集するだけで実行ファイルを更新できる。今でもエンタープライズ・システム(メインフレーム)業界では PL/I や COBOL が重要なスキルであり、科学技術計算では FORTRAN 77 が日常的に使われている。

通常のコンパイル型言語では、ソースファイルをマシン語の実行ファイルに変換してから実行する。実行ファイルは OS を介して機械を直接操作するために動作が速い。それに対してインタプリタ型言語では、ソースファイルを実行時にマシン語に翻訳しながら実行するため、事前にコンパイルする手間は省かれ手軽ではあるが、動作速度は遅くなる。

いずれにしても、実行されるのは機械語である。どの時点で機械語に翻訳するかで、プログラミング言語の種類が別れる。

コンパイル型とインタープリタ型

コンパイラ型の場合は、コンパイルすることによって、どのようなマシン語のモジュールが生成されるか分からないという問題がある。同じソースを同じコンパイラでコンパイルすれば、同じモジュールが生成されるはずであるが、コンパイル時の環境に応じて、異なるモジュールとなる危険を孕んでいる。従って、ソースコードの改変が無くとも、リコンパイル時には、モジュールのユニット単位のテストを再実行することが普通だ。

一方、インタープリタ型の場合は、ソースを実行の都度コンパイルしながら実行するので、このような検討をする必要がない。インタープリタ型の場合でも、実行環境に応じて、どのように機械語に翻訳されるかは異なるのだが、そのような問題は織り込んだ上で実装されるので、問題として取り上げられることは殆どない。

インタープリタ型の場合は、ソースをコンパイルしながら実行するインタープリタが複雑でサイズが大きくなる問題がある。動作速度も低速になる。

Java の場合は、JVM というインタープリタで実行するが、実行対象は、ソースコードそのものではなく、コンパイラ javac によるコンパイルによって生成されたバイトコードである。バイトコードは、JVM 上で実行されるマシン語であると共に逆アセンブル可能である。

裸のソースコードではなく、コンパイル済みのバイトコードを取り扱うようにしたことで、JVM は軽量/高速となったのだ。コンパイルが一回で済み、異なるプラットフォームでも再コンパイルの必要がない点は、コンパイラ型に対するアドバンテージとなる。

一方で、インタープリタである JVM が、バイトコードをどのように扱うかは、実行時の状況に応じて異なるため、モジュールの動作が一意的ではないという問題を孕んでいるのも事実である。

Java は、まさしく、コンパイラ型とインタープリタ型の中間に位置するものだということができる。

Java の実行形態と特徴

概要

Java は、物理的には、ソースコードをバイトコードに変換する。これを、OSにインストールされたインタープリタが解釈/実行している。概念的には、マシンを管理しているOSの上に、仮想的なマシンである JavaVM を導入し、この JavaVM に向けてソースコードを記述してコンパイル/実行しているようにみなせる。コーディング中は、JavaVM より先のOSまで考える必要はない。

実行手順

まず、 Java コンパイラである "javac" がソースファイルを読み込んで、 JavaVM (Java Virtual Machine) 用の中間言語を生成する。これは、全ての命令が1バイトなのでバイトコードと呼ばれる。

続いて、このバイトコードを JavaVM の実体であるインタープリタ "java" が、当該マシン特有のマシン語(機械語)に翻訳しながら実行する。

Java の実行/開発環境。ソースコードを書き、コンパイルしてバイトコードに変換し、 JavaVM がインタープリタでネィティブな OS を介して実際の機械を操作する。
図: Java の実行/開発環境

特徴

Java は、ソースファイルをマシン語に近いバイトコードにコンパイルし、実行時にバイトコードをマシン語に翻訳する。バイトコードのマシン語変換と実行は、ソースファイルのマシン語変換と実行に比べて、実行の高速化、インタープリタ設計の容易化、サイズの低減が実現できる。

他方、コンパイル型言語と比べると、実行時にバイトコードをマシン語変換するプロセスが増えているので、コンパイル型言語より早いと言うことは原理的にありえない。

しかし、 Java でも実行速度を向上させる工夫が成されている。予めコンパイル/最適化して実行ファイルを作成する JIT (Just-In-Time) コンパイラ、バイトコードをマシン語に翻訳するときに問題のある個所だけ、マシンに最適化してコンパイルしておくインタープリタ Java HotSpot Runtime の実装など、パフォーマンス向上の工夫がなされており、実行速度の面は現在ではさほど深刻な問題ではなく、処理系のパフォーマンス向上/最適化技術の向上によって、既存のコンパイル型言語より早いことも珍しくない。

マルチ・プラットフォーム

Java のような中間言語方式の優位性は、実行マシンを問わないことだ。

コンパイル型言語の場合、実行ファイルがそのマシンの固有のコードで用意される。したがって、 Windows 用(intel 系 CPU)の実行ファイルと Macintosh 用(POWER 系 CPU)の実行ファイルとには互換性が無い。

インタープリタ型言語の場合、実行ファイルはテキストのソースファイルであるから、異なるOS/CPUでも互換性を持つが、実行環境にインタープリタが用意されていることが前提になる。インタープリタはサイズが大きく、必ずしも全ての環境に用意できるわけではない。

中間言語方式では、用意するファイルは一つの中間コードであるバイトコードだけで良い。 JavaVM が実装されたマシンでは、 JavaVM に実装されたインタープリタが当該マシン固有のマシン語に翻訳し、ネイティブコードを利用して実行してくれる。バイトコードからマシン語へ翻訳しながら実行するインタープリタは比較的サイズを小さくできる。JavaVM はマシン固有であることが必要だが、バイトコードから見れば JavaVM がマシンの固有性を吸収してくれことになる。

Java プログラムの種類

Java はネットワークのクライアント/サーバ (C/S) 環境を意識して設計されており、その実行場所/仕組みに応じて次のように分けられる:

Java アプリケーション
単なるJavaプログラムで、 javac でコンパイルし、 JavaVM 上のインタープリタが実行する。
Java アプレット
C/S 環境のクライアント側(ブラウザ上)で実行する Java アプリケーション。プログラムをサーバ側に用意しておき、JVMを実装したクライアントがブラウザでアクセスした際に、プログラムをダウンロードして、ブラウザ上のJVMで実行する。「アプレット」は「小さいアプリケーション」という意味だそうだ。
Java Webアプリケーション
C/S 環境のサーバ側で実行する Java アプリケーション。クライアント側にJVMは必須ではない。サーブレットとJSP (JavaServer Pages)がプレゼンテーションロジック層の基礎技術であり、ロジックはBeanと呼ばれるPOJO (Plain Old Java Object)で記述する。Java EE 5以上の仕様では、JSF (JavaServer Faces)が追加された。また、ビジネスロジック層の実装では、EJB (Enterprise Java Bean)、DI (Dependency Injection)、Java Web Serviceなどの基礎技術が使われている。特に、Java EE 5では、EJB 3.0仕様で大きな変更が加えられ、Java Webサービス仕様もより現実的な仕様に充実している。現在でも、多くのシステムの適用業務開発は、JSPとサーブレットを基礎技術として開発されている。

バイトコードをサーバから読み込んで、クライアント側で実行するアプレットは、サーバの負荷分散/ソフトウェアのバージョン管理という観点で優れているため、ウェブサイトのコンテンツに良く使われていた。2002年の最初期に公開されたのは踊るデュークだった。2008年現在、アプレットはリッチクライアント市場から姿を消した。現在は、Ajax/REST, Flash/FLEXで実装するのが主流である。

サーバ側で実行した結果をクライアントに返すサーブレットは、クライアント側の処理能力を問わず管理が容易になるため、C/S環境と基幹業務システム/DB 連携などのときに、業務アプリケーション開発言語としてほぼ標準的な地位を築いている。



Copyright © 2001-2008 SUGAI, Manabu. All Rights Reserved.
SEO [PR] !uO z[y[WJ Cu