🤖

Java仮想マシン(JVM)を読解しながら理解する #4

に公開

https://zenn.dev/h_kohe/articles/45c3d677915b73
こちらの記事の続きです。

よんでいる公式ドキュメント
https://docs.oracle.com/javase/specs/jvms/se17/html/jvms-2.html

2.5. Run-Time Data Areas(ランタイムデータ領域)

JVMがJavaプログラムを実行する際、データを保持するための領域は大きく以下の2つに分かれます。

種類 作成タイミング 破棄タイミング 主な用途
JVM起動時に作成(共有) JVM開始時 JVM終了時 メソッド領域、ヒープなど
スレッドごとに作成(個別) スレッド開始時 スレッド終了時 PCレジスタ、JVMスタック、ネイティブメソッドスタック

2.5.1. The pc Register(pcレジスター)

まず。。。。
pc(プログラムカウンタ)とは??から読解していきます!!

プログラムの「どこを実行しているか」を示す 命令のアドレス(位置) を保持する場所
JVMでは、現在実行中のバイトコード命令の位置 が記録される
プログラムカウンタが更新されることで、次に実行する命令が決まる

とのことです。

1. スレッドごとに専用のPCレジスタ

  • JVMはマルチスレッド実行が可能。
  • 各スレッドは独立した実行経路を持ち、並行して命令を進める。
  • そのため、スレッドごとに**「現在の命令位置」**を記録する必要がある。
  • この役割を担うのがPCレジスタ
  • メリット:スレッド切り替えが発生しても、他スレッドの実行位置が混ざらない。

2. Javaメソッド実行中はバイトコードの位置(オフセット)を保持

  • Javaソースはコンパイルされてバイトコードとなり、メソッド単位で実行される。
  • PCレジスタは、**現在実行中のバイトコードの命令位置(オフセット)**を保持。
  • 0x0015 → メソッド内の16番目の命令。
  • 命令を1つ実行するたびにPCレジスタが更新され、次に実行すべき命令が決まる。

3. nativeメソッド実行中は値が未定義

  • nativeメソッドは、JavaではなくC/C++などのネイティブコードで実装。
  • この間、JVMのバイトコード実行サイクルは一時停止。
  • PCレジスタに「バイトコード位置」という意味のある値を保持できないため、未定義となる(仕様で許容されている)。

4. JVM実装依存の要素

  • PCレジスタの概念はJVM仕様で定義されているが、
    • メモリ上での表現方法
    • ビット幅
    • 実装方法(ハードウェアレジスタ使用 or メモリ変数)
      はJVM実装(HotSpot、OpenJ9、GraalVMなど)に依存。
  • 実機CPUのレジスタを直接使うケースもあれば、専用の変数で管理するケースもある。

上記内容から
スレッド切り替えがあっても、それぞれのPCレジスタが位置を記録しているため、中断した場所から正確に再開可能 になっています。

次は。。。レジスタ(Register)です!!

レジスタは、CPUや仮想マシンが持つ非常に高速にアクセスできる小さな記憶領域
CPUや仮想マシンが今すぐ必要なデータを置いておく場所

これらの内容を踏まえると・・・
pcレジスタ: 「今どこを実行しているか」を覚えておく場所
と理解しました。
そして、中身や記憶領域の置き場所はJVMの作り手が自由に設計できるため、同じJavaプログラムでもJVMの種類によって内部のPCレジスタの構造は異なるとのこと。

まだランタイムデータ領域の章は続きますが、今日はこのへんで切り上げます🙇

まとめ /  得た知見

  • PCレジスタは、JVMにおける「現在実行中の命令位置」を保持する領域であり、プログラムの進行を管理する役割を持つ
  • 各スレッドに専用のPCレジスタが存在し、マルチスレッド実行時でも他スレッドの進行位置と干渉せず、中断地点から正確に再開可能
  • Javaメソッド実行中はバイトコードの位置を記録し、命令ごとに更新される
  • PCレジスタはJVM仕様で概念のみ定義され、内部表現(メモリ管理方法、ビット幅、ハードウェアレジスタ利用の有無など)はJVM実装(HotSpot、OpenJ9、GraalVMなど)に依存。
  • レジスタは高速アクセス可能な記憶領域であり、PCレジスタはその中でも「今どこを実行しているか」を記録することに特化している

Discussion