プログラミング言語における仮想マシンとは?
言語の仮想マシンは、bytecodeで書かれたプログラムを実行するソフトウェアruntimeで、下にある実際のCPUとOSの詳細を隠します。
これは、OS全体を動かすものとは別の種類の仮想マシンです。言語VM、たとえばJava Virtual Machineや.NET Common Language Runtimeは、bytecodeを読み込んで実行するプログラムです。メモリ管理、スレッド処理、一貫した実行モデルを提供するため、同じコンパイル済みプログラムが、VMがインストールされているどこでも同じように振る舞います。
言語VMが提供するもの
言語VMは、プログラムに狙うべき抽象マシンを与えます。定義された命令セット (bytecode) 、自動メモリ管理、標準ライブラリです。あなたのコードはVMと会話し、VMがあなたに代わって実際のハードウェアと会話します。
システムVMとは同じではない
システム仮想マシン (VMwareやクラウドで作られるものなど) は、コンピュータ全体をエミュレートし、ゲストOSを動かします。言語VMは、1つのbytecode形式のプログラムを動かすだけです。名前は共通ですが、異なる問題を解決します。
VMがあなたの代わりに処理するもの
- メモリの割り当てとガベージコレクション。
- ホットなbytecodeのネイティブコードへのjust-in-timeコンパイル。
- スレッドのスケジューリングと同期プリミティブ。
- 異なるCPUやOSをまたぐ移植性のある抽象化。
なぜVMは移植性で勝るのか
VMがプラットフォームの違いを吸収するため、1つのコンパイル済みartifactがLinux、macOS、Windowsで変更なしに動きます。あなたはbytecodeを出荷し、存在するVMがそれを正しく実行します。
簡単な例
java -jar app.jar を実行するとJVMが起動し、あなたのbytecodeを読み込み、忙しい部分をJITコンパイルし、メモリを管理し、プログラムを実行します。あなたはCPU命令を自分で書くことはなく、VMが行います。
CIにおける言語VM
VMベースの言語はメモリを多く使うことがあり、VMのheapサイズが重要です。設定したheapを超えるテストスイートはout-of-memoryエラーを投げ、runnerに強制終了されることがあります。より大きなrunner (Latchkey) はVMに余裕を与え、一時的なOOMによる強制終了は自動でリトライできるため、flakyなリソースのスパイクがmergeをブロックしません。
重要なポイント
- 言語VMはbytecodeを実行し、下にあるCPUとOSを抽象化します。
- コンピュータ全体をエミュレートするシステムVMとは別物です。
- VMは、メモリ、スレッド、JITコンパイルをあなたの代わりに処理します。