コンパイルやインタプリタってなに?

プログラム実行の基礎的な仕組みを理解しよう

プログラム実行のための基本的な仕組み

プログラミングを学習しはじめると、C/C++やJavaなどの言語だと特ににコンパイル、ビルド、ライブラリ、モジュールなどの言葉が飛び込んできます。これらを詳しく理解する必要はないですが、必要最低限ざっくりとした全体の仕組みを把握しておかないと、意味がわからず挫折しかねません。ここでは、これらプログラム実行の基礎的な仕組みを簡単に説明したいと思います。これだけ知っておけば参考書などに書いてあることが理解できるようになるかと思います。

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

プログラムは実行できるようにするためにコンパイルが必要なものとそうでないものがあります。コンパイルとはプログラムが実行できるようにするための手続きです。プログラムは人が理解できるように記述された文書です。それを機械が理解できるように書き換える作業をコンパイルといいます。(プログラムをコンパイルするプログラムのことをコンパイラといいます。)

コンパイルの必要がなく動作するプログラムはインタプリタという仕組みで動作します。インタプリタがコンパイルと同じような作業を自動で実行してプログラムが動作しているのです。ではなぜコンパイルの必要な言語とそうでないものがあるのでしょうか。

詳細にはコンピュータが生まれた経緯や歴史的背景から様々な理由がありますが、大きくは2つの理由が考えられます。

  1. プログラムの実行速度を優先するとコンパイルが必要
  2. プラットフォーム互換性を優先するとインタプリタで動作

1について、プログラムはコンピュータの種類(CPU)に合わせて実行ファイルを作る必要があります。これはコンピュータの脳にあたるCPUは内部の計算処理の方法が種類によって違うためです。例えば、C言語はコンパイルが必要です。コンピュータの種類ごとにコンパイラがあります。プログラムが大きいほどコンパイルに時間がかかりますが、作成された実行ファイルの処理速度は速いです。

インタプリタはこのコンパイル作業をプログラム実行と同時に自動で行いますが、時間のかかるコンパイルを行いながら実行するのは現実的ではありません。なので、インタプリタで動作するプログラミング言語は、自動的にコンパイル作業しながらある程度の実行速度を保てるように設計されているのです。その代わりコンピュータの種類ごとにインタプリタを用意しておけば、コンパイルの必要なく1つのプログラムでどの環境でも動作できるようなり、プラットフォーム互換性が高くなります。

また、この2つの特徴を出来る限り活かしたJIT方式という方法で実行するプログラムもあります。

プログラムから実行ファイルを作成するまでの流れ

コンパイルはプログラムを実行できるようにするための1つの作業です。パソコンやスマホなどで動かしているアプリは実行できるようになったバイナリコードです。

テキストエディターなどを使って記述するプログラムをソースコードと言います。ソースコードをコンパイルして作成されるものをオブジェクトコードと言います。このオブジェクトコードを繋ぎ合わせて実行可能なバイナリコードを作成します。実はコンパイル「作業」の必要がないプログラムも例外なくこの手順で動作しています。つまり、プログラム作成者が明示的にコンパイルすることが必要な言語とそうでない言語があるのです。

アプリ開発ではよく「ビルド」という言葉がでてきます。ビルドは統合開発環境(IDE)にある機能です。IDEはソースコード編集、コンパイル、実行ファイル生成、デバッグ、アプリ実行など開発に必要な機能が全て備わっています。こういった開発作業を「プロジェクト」単位で管理できるようになっています。そしてプロジェクトでアプリ動作確認やデバッグをできるようにしながらアプリを作成する機能をビルドといいます。最近では「アプリ作成=ビルド=コンパイル」といった感じで、ビルドもコンパイルも同じ意味で使われることが多くなっています。

コンパイル作業の必要がないプログラムはなぜ動くのでしょうか。これらの言語は「コンパイル ー> バイナリコード作成 ー> 実行」までの一連の作業をインタプリタという仕組みで動作させているためです。

<インタプリタ方式>

インタプリタが自動的にコンパイル作業をするので、作成したプログラムをそのまま実行できるのです。LinuxとMacのターミナルやWindowsのコマンドプロンプトを使ってプログラムを実行させるとわかりやすいのですが、コンパイルしたプログラムを実行するときは、コンパイルによって作成されるファイル名の入力で実行できます。一方、コンパイル作業が必要のないプログラムを実行するときは、コマンド入力の後に実行するプログラムファイル名を入力します。例えば、

python sample.py

のように入力します。sample.pyはプログラム(ソースコード)が書かれたファイルです。

ただしJavaはそれらとは違い、コンパイルを必要とし、且つインタプリタ方式のように実行します。正確には、インタプリタに相当する部分は「JIT(Just-In-Time)コンパイル」といいます。

<JIT方式>

これは実行されるそのときにコンパイルするのでこのように名付けられています。このJavaのJITコンパイルするための環境はJVM(Java Virtual Machine)と呼ばれています。Javaがプログラムを実行するためにJIT方式を選んだのには大きく2つの理由があります。

  1. 実行時にオペレーティングシステムやCPUに依存しないソースコードやオブジェクトコードを配布して実行できるようにする
  2. インタプリタ方式よりもJIT方式のほうが実行速度がはやい(処理速度が速い)

コンパイルは、コンパイルを実行するオペレーティングシステムやCPUに依存して実行ファイル(バイナリコード)を作成します。JavaはOSやCPUに依存せず、なおかつ、実行速度の速い方法を考慮してJIT方式になりました。

ライブラリとモジュール

上記の説明に書かれた図にある「ライブラリ」「モジュール」について説明します。ライブラリは、利用する関数・データが集まったものです。そのライブラリを利用しているプログラムとリンクすることで実行できるようになります。モジュールは、一連の機能をひとまとめにしたバイナリコードです。モジュール単位でテストすることもできるようになるため、各モジュールで並行してテストできるため効率よく開発することができます。プログラムは規模が大きくなると処理も複雑になります。そうすると可能な限り効率よく開発できるようにする必要があります。効率よくしないと、プログラムが期待通りの動作をしないときの問題を解決するのにとても時間がかかったり、プログラムのどの部分にどの機能があるのか分からなくなり、メンテナンスにとても労力がかかります。ライブラリ化やモジュール化することで、大きなプログラムの中で同じ機能が各所で必要だったり、テストをより速く正確にすることができます。

おわり

以上がプログラム実行の基礎知識となります。プログラムを実行するための仕組みについて基礎的なことを知るだけで、参考書などの説明の意味も理解しやすくなるでしょう。