🤖

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

に公開

https://zenn.dev/h_kohe/articles/0415315d4dd8b9
こちらの記事の続きです

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

先日、人生初のハッカソンに参加してきたのですが。。。
イベントを企画して運営する難しさを体験する1日でした。
企画運営をしてくださった皆さま、ありがとうございました!!
今度は参加者ではなく、企画運営側で携わってみたいな・・・

さて、少し間隔が空いたのですが今回もJVMを読み進めていきます。

2.5.4. Method Area(メソッド領域)

今回もかなり重要そうな項目ですね・・・!!

メソッド領域とは?

•JVM起動時に作成される
•JVM 内で すべてのスレッドに共有されるメモリ領域
•クラスごとの情報 を保持する
(定数プール、フィールド・メソッド情報、メソッド/コンストラクタのコードなど)
•メモリ不足になると OutOfMemoryError が発生

そして、下記内容はJVMの実装者に委ねられる項目です。

•論理的にはヒープの一部だが、GCや圧縮を行わない実装もある
•サイズは固定 or 可変(拡張・縮小できる)
•連続したメモリである必要はない
•ユーザーが初期サイズ・最大/最小サイズを設定できる場合がある

ここまでは、公式ドキュメントに記載されていた内容を要約しただけですが・・・
では、ヒープ領域とメソッド領域は何が違うのか??と疑問になりませんか??🧐

メソッド領域とヒープ領域の違い

気になったので以下の表に差異をまとめました!!

領域 格納されるもの 主な用途 GC対象か
ヒープ new で作られたオブジェクト、配列 インスタンスのライフサイクル管理 GCの主な対象
メソッド領域 クラス情報、メソッドコード、定数プール、static変数 プログラムの構造・設計図を保持 GCの対象になる場合もあるが、クラスアンロード時にも開放される

ここまでの内容をまとめると・・・

ヒープは「モノ置き場」、メソッド領域は「設計図置き場」
設計図は普段捨てられないけれど、クラスごとに不要になったときだけ捨てられる

2.5.5. Run-Time Constant Pool(実行時定数プール)

なんかまた直訳だけ意味が分かりそうで、分かりにくそうな項目ですね・・・😇

実行時定数プールとは?

•クラスやインタフェースごとに作られる定数の倉庫
•各実行時定数プールは JVMのメソッド領域 から確保される
•実行時定数プールの構築に必要なメモリをメソッド領域から確保できない場合、JVM は OutOfMemoryError をスロー

んーーー なんかイメージつきそうでつかない・・・😇
とりあえず、先ほど登場したメソッド領域の一部のようですが
具体的に何を管理しているのでしょうか??

メソッド領域と実行時定数プールの違い

領域 単位 役割 主な内容
メソッド領域 JVM 全体で共有 クラスやインタフェースの「設計図置き場」 フィールド定義、メソッド定義、バイトコード、static変数、実行時定数プール
実行時定数プール クラス/インタフェースごと 設計図に付属する「辞書・参照リスト」 数値リテラル、文字列リテラル、クラス参照、メソッド・フィールド参照

なるほど!!
個人的には表にすることで結構納得感がありました。

2.5.6. Native Method Stacks(ネイティブメソッドスタック)

さあ。。。長かった2.5章も最後の項目です!!
公式ドキュメントを翻訳して読んでいるのですが・・・よくわからない項目だったので頑張って読解していきます!!

ネイティブメソッドスタックとは?

•Java 以外の言語(例:C 言語)で書かれた ネイティブメソッドを実行するためのスタック

さあ。。。早速もう謎です😇

今まで実装で触れたことはなかったのですが、native修飾詞ってものが存在するんですね・・・😦
https://java-code.jp/120

種類 実装場所 実行方法 主な用途
普通のJavaメソッド Java (バイトコード) JVM が解釈 / コンパイルして実行 通常のアプリケーション処理
ネイティブメソッド C / C++ など native キーワード + JNI を通じて実行 OS機能利用、外部ライブラリ連携、最適化処理
※JNI (Java Native Interface) :Java と C/C++ の橋渡しをする仕組み/Java から OS の機能や外部ライブラリを呼び出すときに使う

エラー時は・・・
•上限超え → StackOverflowError
•メモリ不足 → OutOfMemoryError

そして、

従来のスタックに依存しないJava仮想マシンの実装では、ネイティブメソッドスタックを提供する必要はありません

と直訳で記載されているで、ネイティブメソッドスタックの実装の要否はC言語スタックに依存するかしないかがによって別れるようです。
つまりピュアJavaのみを解釈するJVMではネイティブメソッドスタックの実装は省略できて、
OracleのHotSpot JVMのような一般的な実装では、標準ライブラリ自身がネイティブメソッドを多用しているため、内部的には必ず利用されているということになります。

まとめ

  • ヒープ … オブジェクトの「モノ置き場」
  • メソッド領域 … クラスやメソッドの「設計図置き場」
  • 実行時定数プール … 設計図に付随する「辞書」
  • ネイティブメソッドスタック … JVMの外の世界(OS/ライブラリ)とつなぐ「橋渡しスタック」

Discussion