Skip to content
Latchkey

bytecodeとは? ソースとハードウェアの間のレイヤー

bytecodeは、マシンコードよりコンパクトで移植性のある中間命令セットで、ネイティブのCPU命令の代わりに仮想マシンが実行します。

多くの言語はマシンコードへ直接コンパイルしません。代わりにbytecodeへコンパイルします。これは仮想マシンと呼ばれるruntimeによって実行されるよう設計された、低レベルでプラットフォーム非依存の形式です。Java、C#、Pythonはいずれもbytecodeを使います。これが「一度書けばどこでも動く」という仕掛けです。一度コンパイルすれば、そのbytecode向けのどのVMでも実行できます。

bytecodeの位置

bytecodeは、人間が読めるソースと生のマシン命令の間に位置します。あなたのソースよりマシンに近いものの、最終ステップをVMが担うため、OSやCPUアーキテクチャをまたいで移植できる程度には抽象的です。

そもそもなぜbytecodeを使うのか

  • 移植性: 同じbytecodeが、対応するVMのあるどのプラットフォームでも動く。
  • 毎回ソースを再parseするより速い読み込み。
  • 言語が最適化の対象にできる安定したターゲット。
  • ホットなコードパスのjust-in-timeコンパイルの基盤。

bytecode vs マシンコード

マシンコードは1つのCPUアーキテクチャに固有で、ハードウェア上で直接動きます。bytecodeは汎用的で、仮想マシンによって実行 (解釈またはさらにコンパイル) される必要があります。移植性のあるbytecodeと実際のプロセッサを橋渡しするのがVMです。

bytecodeがどう実行されるか

VMはbytecodeを命令ごとに解釈することも、just-in-timeコンパイラを使って頻繁に走るbytecodeをその場でネイティブコードへ翻訳することもできます。これが、長時間動くJavaや.NETのプログラムがウォームアップ後に速くなる理由です。

簡単な例

Pythonスクリプトを実行すると、インタプリタは各モジュールをbytecodeにコンパイルし、それを __pycache__ ディレクトリに .pyc ファイルとしてcacheすることがあります。次の実行では、ソースの再parseを省いてbytecodeを直接読み込めます。

CIにおけるbytecode

buildステップは、後の段階が消費するbytecodeのartifact (JAR、DLL、cacheされた .pyc ファイル) を生成することがよくあります。これらをrunをまたいでcacheするとpipelineが速くなりますが、破損したり部分的なcache取得は紛らわしい失敗を招くことがあります。マネージドrunner (Latchkey) はcacheを温かく保ち、一時的なcacheやregistryの不調を自動でリトライします。

重要なポイント

  • bytecodeは、CPUが直接ではなく仮想マシンが実行する、移植性のある中間形式です。
  • 一度書けばどこでも動く移植性と、より速いプログラム読み込みを可能にします。
  • VMはbytecodeを解釈するか、ホットなパスをネイティブコードへJITコンパイルします。

関連ガイド