Revised: Nov./17th/2003; Since: Dec./23rd/2001
ここでは Java のコンピュータ言語としての特徴をまとめておく。興味が無ければ飛ばしても構わない。但し、後続の章で分からないことがあれば、戻ってくるように勧める。
実行形式で分類すると、 Java はインタープリタ型言語である。ただし、純粋なインタープリタ言語ではなく、中間言語方式などと呼ばれる。
![]() |
図:アプリケーションの実行形態 |
---|
メインフレーム全盛期には、HEX Dump(16進ダンプ)を見てニーモニックに翻訳できる人がいて、"walking assembler/disassembler" と呼ばれていた。プログラム全体を、構造化プログラミングという手続きに従ってモジュール化することによって、一部が変更されても、そのモジュールを連係編集するだけで実行ファイルを更新できる。今でもエンタープライズ・システム(メインフレーム)業界では PL/I や COBOL が重要なスキルであり、科学技術計算では FORTRAN 77 が日常的に使われている。
通常のコンパイル型言語では、ソースファイルをマシン語の実行ファイルに変換してから実行する。実行ファイルは OS を介して機械を直接操作するために動作が速い。それに対してインタプリタ型言語では、ソースファイルを実行時にマシン語に翻訳しながら実行するため、事前にコンパイルする手間は省かれ手軽ではあるが、動作速度は遅くなる。
いずれにしても、実行されるのは機械語である。どの時点で機械語に翻訳するかで、プログラミング言語の種類が別れる。
コンパイラ型の場合は、コンパイルすることによって、どのよなマシン語のモジュールが生成されるか分からないという問題がある。同じソースを同じコンパイラでコンパイルすれば、同じモジュールが生成されるはずであるが、コンパイル時の環境に応じて、異なるモジュールとなる危険を孕んでいる。従って、ソースコードの改変が無くとも、リコンパイル時には、モジュールのユニット単位のテストを再実行することが普通だ。
一方、インタープリタ型の場合は、ソースを実行の都度コンパイルしながら実行するので、このような検討をする必要がない。インタープリタ型の場合でも、実行環境に応じて、どのように機械語に翻訳されるかは異なるのだが、そのような問題は織り込んだ上で実装されるので、問題として取り上げられることは殆どない。
インタープリタ型の場合は、ソースをコンパイルしながら実行するインタープリタが複雑でサイズが大きくなる問題がある。動作速度も低速になる。
Java の場合は、JVM というインタープリタで実行するが、実行対象は、ソースコードそのものではなく、コンパイラ javac によるコンパイルによって生成されたバイトコードである。バイトコードは、JVM 上で実行されるマシン語であると共に逆アセンブル可能である。
裸のソースコードではなく、コンパイル済みのバイトコードを取り扱うようにしたことで、JVM は軽量/高速となったのだ。コンパイルが一回で済み、異なるプラットフォームでも再コンパイルの必要がない点は、コンパイラ型に対するアドバンテージとなる。
一方で、インタープリタである JVM が、バイトコードをどのように扱うかは、実行時の状況に応じて異なるため、モジュールの動作が一意的ではないという問題を孕んでいるのも事実である。
Java は、まさしく、コンパイラ型とインタープリタ型の中間に位置するものだということができる。
Java は、物理的には、ソースコードをバイトコードに変換する。これを、OSにインストールされたインタープリタが解釈/実行している。概念的には、マシンを管理しているOSの上に、仮想的なマシンである JavaVM を導入し、この JavaVM に向けてソースコードを記述してコンパイル/実行しているようにみなせる。コーディング中は、JavaVM より先のOSまで考える必要はない。
まず、 Java コンパイラである "javac
" がソースファイルを読み込んで、 JavaVM (Java Virtual Machine) 用の中間言語を生成する。これは、全ての命令が1バイトなのでバイトコードと呼ばれる。
続いて、このバイトコードを JavaVM の実体であるインタープリタ "java
" が、当該マシン特有のマシン語(機械語)に翻訳しながら実行する。
![]() |
図: Java の実行/開発環境 |
Java は、ソースファイルをマシン語に近いバイトコードにコンパイルし、実行時にバイトコードをマシン語に翻訳する。バイトコードのマシン語変換と実行は、ソースファイルのマシン語変換と実行に比べて、実行の高速化、インタープリタ設計の容易化、サイズの低減が実現できる。
他方、コンパイル型言語と比べると、実行時にバイトコードをマシン語変換するプロセスが増えているので、コンパイル型言語より早いと言うことは原理的にありえない。
しかし、 Java でも実行速度を向上させる工夫が成されている。予めコンパイル/最適化して実行ファイルを作成する JIT (Just-In-Time) コンパイラ、バイトコードをマシン語に翻訳するときに問題のある個所だけ、マシンに最適化してコンパイルしておくインタープリタ Java HotSpot Runtime の実装など、パフォーマンス向上の工夫がなされており、実行速度の面は現在ではさほど深刻な問題ではなく、処理系のパフォーマンス向上/最適化技術の向上によって、既存のコンパイル型言語より早いことも珍しくない。
Java のような中間言語方式の優位性は、実行マシンを問わないことだ。
コンパイル型言語の場合、実行ファイルがそのマシンの固有のコードで用意される。したがって、 Windows 用(intel 系 CPU)の実行ファイルと Macintosh 用(POWER 系 CPU)の実行ファイルとには互換性が無い。
インタープリタ型言語の場合、実行ファイルはテキストのソースファイルであるから、異なるOS/CPUでも互換性を持つが、実行環境にインタープリタが用意されていることが前提になる。インタープリタはサイズが大きく、必ずしも全ての環境に用意できるわけではない。
中間言語方式では、用意するファイルは一つの中間コードであるバイトコードだけで良い。 JavaVM が実装されたマシンでは、 JavaVM に実装されたインタープリタが当該マシン固有のマシン語に翻訳し、ネイティブコードを利用して実行してくれる。バイトコードからマシン語へ翻訳しながら実行するインタープリタは比較的サイズを小さくできる。JavaVM はマシン固有であることが必要だが、バイトコードから見れば JavaVM がマシンの固有性を吸収してくれことになる。
Java はネットワークのクライアント/サーバ (C/S) 環境を意識して設計されており、その実行場所/仕組みに応じて次のように分けられる:
バイトコードをサーバから読み込んで、クライアント側で実行するアプレットは、サーバの負荷分散/ソフトウェアのバージョン管理という観点で優れているため、ウェブサイトのコンテンツに良く使われる。
サーバ側で実行した結果をクライアントに返すサーブレットは、クライアント側の処理能力を問わず管理が容易になるため、 C/S 環境と基幹業務システム/DB 連携などのときに、業務アプリケーション開発言語としてほぼ標準的な地位を築いている。
当初は Web 上で動的なコンテンツを開発する汎用言語として注目された Java だが、アプレット・サイズ、 Wintel 連合と Sun Microsysytems の不和などにより、 2001 年現在は下火になっている。サーバーサイドへの移行に伴い、マルチメディアコンテンツ開発用途は消え去るかもしれない。
他にも、パブリック・コンポーネントである Enterprise Java Beans (EJB)、サーブレットの表示部分を特化した Java Server Pages (JSP)、データベース連携の JDBC などを説明するべきかもしれないが、追々説明することにする。いずれの場合でも、コーディングのシンタックスやセマンティックスは同じである。