← Spring コース
35. JVM の起動とクラスロード、JIT
Hello を実行すると、 は必要なを読み込みます()。 25 でログを出すと 609 行あり、自分の Hello は 401 行目でした。その前の 400 個は String など です。Hello の後にも、文字列の連結に使う StringConcatFactory などが、使う段になってから読み込まれていました。
読み込んだはまず解釈しながら実行され、よく通る箇所は が実行中にへ置き換えます。Rust が先に機械語を作るのに対し、Java は走りながら作ります。JDK 25 とこの機械で同じ計算を 2000 ラウンド回した実測(3回)では、1ラウンド目が 689〜1176 マイクロ秒、後半の中央値は 69 でした。下のコードは回数を減らした別のプログラムで、数値は環境ごとに変わります。
起動時間の実測です( の 上、各10回を2巡し、各巡の1回目は除く)。java Hello は 14〜17 ミリ秒、node hello.js は 10〜12 ミリ秒です。Rust は 0.7〜2.0 ミリ秒(外れ値が1回)で、何もしないプロセスとほぼ区別できません。Hello の規模では JVM と Node の差は数ミリ秒で、JVM 一般の速さは言えません。 アプリの起動は後のレッスンで扱います。
点線の付いた語はタップすると説明が出ます。用語集を開く →
java HelloJVM のプロセスが起動する
クラスロード
JDK 自身のクラスこの実測では先に 400 個。大半は共有アーカイブから取り込む
401 番目
Hello を読み込み、main を呼ぶ場所は file:/w/(クラスパス上のディレクトリ)
実行
インタプリタバイトコードを解釈して実行
JIT コンパイラよく通る箇所を実行中に機械語へ
- ・609 行・401 行目は、この Hello を JDK 25.0.4.1 の既定オプションで動かしたときの値です。JDK 22 では同じ Hello で 531 行でした
- ・JVM の仕様は機械語へ訳すかどうかを実装に任せています。ここでの JIT は、Temurin が採用している HotSpot という実装の動きです
- ・java マニュアル(JDK 25)は既定の動作を「Executes all bytecode by the interpreter except for hot methods, which are compiled to native code.」と説明しています。-Xint で解釈実行だけにすると、同じ実測は最後まで約 600 マイクロ秒のままでした
- ・共有アーカイブ(CDS)を切ると(-Xshare:off)、起動は各巡の1回目を除いて 30〜34 ミリ秒になり、既定の約2倍でした
▶ サンプルコードを実行してみよう(自由に書き換えてOK)
Java
図やコードに出てくる用語(タップで説明)
サンプルコードで身につける(5本) →
学んだ概念を、素朴な例から実務寄りの例まで5つの具体例で確認します。
公式ドキュメントで詳しく ↗