pubDate: 2024-05-31
author: sakakibara
C, Java, Pythonはどれも人気も歴史もあるプログラミング言語であるがそれぞれプログラミングの実行が異なる。
C言語は主にgccというコンパイラを用いてソースコードを実行できるファイルに変換する。 このファイルはExecutable and Linkable Format(ELF)と呼ばれる形式である。 ELFはUnix系OSで使われ、実行可能ファイル、オブジェクトコード、共有ライブラリ、コアダンプなどを扱うために設計されている。
ELFは以下の内容を持つ。 つまり、C言語のメモリレイアウトはELFの実行時のプロセスのメモリレイアウトそのものであると言える。
内容 | 説明 |
---|---|
ヘッダー | ファイルの種類、マシンアーキテクチャ、エントリポイントのアドレスなど、ファイルに関するメタデータ |
テキストセグメント | プログラムの実行コードが含まれる。この部分がプログラムの”機械語”を直接含んでいる。read-only。 |
データセグメント | 初期化済みのグローバル変数や静的変数を含む。実行中に読み書きが行われる。 |
未初期化データセグメント(BSS) | 初期化されていないグローバル変数や静的変数を含む。(実際にはファイルには格納されず、実行時にメモリに確保される)。 |
リロケーション情報 | プログラムが正しく動作するために必要なアドレス修正情報が含まれる。 |
シンボルテーブル | 関数や変数の名前とアドレスの対応関係など、デバッグやリンクに必要な情報を含む。 |
ELFファイルのテキストセグメントにはプログラムの機械語された内容が含まれている。
これによって、Unix系のOS上で直接実行できる。
Tool Interface Standard (TIS) ELF GitBook
Javaはjavacというプログラムでソースコード(.java)が中間バイトコード(.classや.jar)に変換される。 中間バイトコード(一般に、仮想マシン上で実行するためにコンパイルされた中間形式)はJVM(Java Virtual Machine)上で実行することができる。 JVMでは内部でさらにJIT(Just In Time)コンパイルによってさらに機械語に翻訳される。 これによってかなりネイティブのプラットフォーム上に近いパフォーマンスを得ることができる。
よく、Javaはプラットフォームに依存しないプログラミング言語などと言われるが、 実際にはJavaもJREと呼ばれる各OSに依存する実行環境を各プラットフォーに異なるバイナリが必要となる。
JVMが管理するメモリレイアウトとしては以下のようなものがある。
内容 | 説明 |
---|---|
PCレジスタ | スレッド毎に実行している現在実行中の命令アドレス(PCアドレス) |
スタック領域 | メソッドの呼び出しやローカル変数 |
ヒープ領域 | インスタンスと配列が格納される。GCによって管理される。 |
メソッド領域(ヒープ領域) | OSのテキストセグメントやC言語のテキスト領域に該当する。クラス構造、メソッドのデータ、メソッドのコード、実行時定数プールなどが格納される。GCの対象外。 |
実行時定数プール (メソッド領域) |
型、フィールド、メソッドにアクセスするための参照やコンパイル時に確保される定数が保持される。 |
ネイティブスタックメソッド | JVMがネイティブコードを実行するために使用する。JVMの命令セット用インタプリタのC言語実装によって使用される。 |
PythonはPython interpleterと呼ばれるインタプリタを通して実行される。 代表的なPython interpleterであるCPythonについて述べる。 CPythonは(.py)で書かれたコードを中間バイトコード(.pyc)にコンパイルし、PVM(Python Virtual Machine)上でインタプリタ形式で実行する。 インタプリタ形式とはいわゆる即時実行であり、バイトコードの一行一行を読み取り解析し、直接実行する形式である。
このため、JITコンパイルのように機械語翻訳されることは無く、毎回バイトコードをインタプリタするために実行が遅くなる。 なお、PypyなどではJITコンパイルされるので速度が向上する。
Pythonのメモリレイアウトは非常に特殊でそれもインタプリタ言語であるためはあるが、 すべてのオブジェクトはヒープ領域に格納される。
内容 | 説明 |
---|---|
ヒープ領域 | Pythonのオブジェクト(数値、文字列、リスト、辞書、関数、クラスなど、なんでも)が格納される。 |
スタック領域 | 関数の呼び出し |
コードオブジェクト | コードはコードオブジェクトとしてヒープ領域に格納される。それもそう、だってインタプリタ言語なのだもの。 |
このように見てみると、C言語、Java、Pythonはそれぞれ異なるプログラミングの実行方法を持っていることがわかる。