第2章 オブジェクト管理機能

HotspotVMではさまざまなGCアルゴリズムを選択できる機能があります。Javaの起動オプションで「-XX:+UseParallelGC」などと指定するアレのことです。GCはそれぞれ管理するヒープの形状が異なり、また当然ですがGCアルゴリズム自体も異なります。本書ではHotspotVMのヒープやGCをまとめてオブジェクト管理機能と呼ぶこととし、本章ではオブジェクト管理機能の全体像を見ていきます。

2.1 オブジェクト管理機能のインタフェース

図2.1にオブジェクト管理機能のインタフェースイメージを示します。

オブジェクト管理機能がVMに公開するインタフェースのイメージ

図2.1: オブジェクト管理機能がVMに公開するインタフェースのイメージ

オブジェクト管理機能はVMに対して主に次の3種類のインタフェースを公開します。

  1. オブジェクトの割り当て
  2. 明示的なGCの実行
  3. オブジェクトの位置や形状に依存した処理

1.は、VMがオブジェクトの種類を指定すると、VMヒープの内部に割り当てたオブジェクトの実体を返してくれるインタフェースです。

2.は、GC実行要求を出すと内部でGCを実行してくれるインタフェースです。

VMはVMヒープ内のオブジェクトの位置や形状がわかりません。そのため、3.が必要になります。具体的には、VMヒープ内の全オブジェクトに指定した関数を適用する、また、あるオブジェクト内の全フィールドに指定した関数を適用する、指定したアドレスが割り当てられたオブジェクトかどうか確認する、といったインタフェース群が定義されています。

上記のインタフェースさえ守れていれば、オブジェクト管理機能の内部実装は好きに変更できます。つまり、インタフェースが同じであれば異なるGCアルゴリズムを実装することも可能なわけです。

VM側は基本的に上記のインタフェースを利用して実装されますが、例外的にオブジェクト管理機能の内部実装を意識する部分もあります。そのような箇所ではGCの種類を判断し、処理を条件分岐しています。

2.2 オブジェクト管理機能内の全体像

図2.2にオブジェクト管理機能内の全体像を示します。

オブジェクト管理機能内の全体像。<tt class="inline-code">CollectedHeap</tt>クラスがインタフェースとなる。<tt class="inline-code">CollectedHeap</tt>クラスは<tt class="inline-code">CollectorPolicyクラス</tt>内の設定値を参考に方針を決定する。また、<tt class="inline-code">CollectedHeap</tt>クラスは各GCクラスに対してヒープ内のGCを要求する。

図2.2: オブジェクト管理機能内の全体像。CollectedHeapクラスがインタフェースとなる。CollectedHeapクラスはCollectorPolicyクラス内の設定値を参考に方針を決定する。また、CollectedHeapクラスは各GCクラスに対してヒープ内のGCを要求する。

まず、登場人物を簡単に説明しましょう。CollectedHeapというクラスはオブジェクトを割り当てるVMヒープを管理します。また、オブジェクト管理機能のインタフェースとして機能し、CollectorPolicyクラスの情報を参照して適切な処理を実行します。

CollectorPolicyクラスはオブジェクト管理機能全体の方針(Policy)を定義するクラスです。このクラスはオブジェクト管理機能に関わる設定値を保持しており、例えば、Javaコマンド実行時に言語利用者がオプションで指定した値(GCアルゴリズムなど)はこのクラスが管理します。

各GCクラスはVMヒープ内のゴミオブジェクトを解放する役割を持ち、主にCollectedHeapクラスに利用されます。アルゴリズムによってGCのクラスはかなり変化しますので、ここでは「各GCクラス」と表現しています。

図2.2のように、VMからオブジェクト割り当て要求がおこなわれた場合は、まずCollectedHeapクラスが要求を受け、CollectorPolicyクラスの方針にしたがって、内部のメモリ空間にあるオブジェクトを割り当てます。もし、メモリ空間に空きがなければ適切な各GCクラスを使ってGCを実行します。

2.3 CollectedHeapクラス

VMヒープを表現するCollectedHeapクラスを詳しく見ていきましょう。

<tt class="inline-code">CollectedHeap</tt>クラスの継承関係

図2.3: CollectedHeapクラスの継承関係

図2.3に示す通り、VMヒープはCollectedHeapという抽象的なクラスで統一的に扱われます。CollectedHeapクラスはVMヒープの形状によって子クラスに派生し、この子クラスがVMヒープの実体となります。

OpenJDK7の起動オプションとVMヒープクラス

表2.1に、OpenJDK7のGCを指定する起動オプションと、GCに対応するVMヒープクラスを示します。

表2.1: 起動オプションと利用するVMヒープクラス

起動オプションGCアルゴリズムVMヒープクラス
-XX:UseSerialGC逐次GCGenCollectedHeap
-XX:UseParallelGC並列GCParallelScavengeHeap
-XincgcインクリメンタルGCGenCollectedHeap
-XX:UseConcMarkSweepGC並行GCGenCollectedHeap
-XX:UseG1GCG1GCG1CollectedHeap

上記を見ていただくとわかるとおり、GCアルゴリズムとVMヒープクラスの対応については特に明確なルールがありません。GenCollectedHeapは複数のGCアルゴリズムから利用されますが、G1CollectedHeapはG1GCしか利用しません。

注意して欲しいのは、GenCollectedHeapという名前から「世代別GCアルゴリズムはすべてこのヒープを利用するのだな」と推測してはいけないという点です。HotspotVMの並列GCやG1GCはGenCollectedHeapを利用しないにも関わらず世代別のアルゴリズムです。

2.4 CollectorPolicyクラス

次に、オブジェクト管理機能の方針を定義するCollectorPolicyクラスを見ていきましょう。

<tt class="inline-code">CollectorPolicy</tt>クラスの継承関係

図2.4: CollectorPolicyクラスの継承関係

図2.4に示す通り、方針はCollectorPolicyという抽象的なクラスで統一的に扱われます。CollectorPolicyクラスはオブジェクト管理機能の方針によって子クラスに派生します。

起動オプションとCollectorPolicyクラス

OpenJDK7のGCを指定する起動オプションと、利用されるCollectorPolicyの子クラスの対応表を表2.2に示します。

表2.2: 起動オプションと利用する方針

起動オプション方針
-XX:UseSerialGCMarkSweepPolicy
-XX:UseParallelGCGenerationSizer
-XincgcConccurentMarkSweePolicyCMSIncrementalMode=true
-XX:UseConcMarkSweepGCConccurentMarkSweePolicy
-XX:UseG1GCG1CollectorPolicy_BestRegionsFirst

CollectorPolicyにはGCに関連するJavaの起動オプションで指定した情報が何らかの形で格納されています。上記のGCを指定する起動オプション以外の代表的な例だと、-Xmsで指定する初期ヒープサイズや、-Xmxで指定する最大ヒープサイズが挙げられます。また、指定したGCに対する細かな設定値、例えばG1GCのMaxGCPauseMillis(最大停止時間)などの情報もCollectorPolicyに格納されます。

CollectedHeapCollectorPolicyに格納された情報を参考にして、自らの実行方針を決定し、適切な処理を実行します。

2.5 各GCクラス

各GCクラスはCollectedHeapによってVMヒープ内部のゴミ収集に利用されます。それぞれのGCクラスは、共通のインタフェースを持っておらず、かなり自由にクラスが定義されています。VMヒープのゴミ収集という達成するという目的だけは一致していますが、GCアルゴリズムによって実装はバラバラで一貫性がありません。しかし、このように自由にクラスを定義してもCollectedHeap側でがんばって吸収してくれるので、VM側にはそれほど影響がありません。

筆者の推測では、どのようなGCアルゴリズムであっても柔軟に追加できるように、GCクラスに関しては自由度を高めているのだと思います。実際、G1GCというかなり特殊なアルゴリズムがGCクラスとして開発され、全体の設計が崩れることなく導入されています。

本書ではG1GCで利用されるGCクラス群だけを説明していきます。ほかのGCクラス群に興味がある場合は、表2.1と表2.2内の対応するCollectedHeapCollectorPolicyを手がかりにしてソースコードを追ってみましょう。


御意見・御感想・誤植の指摘などは@nari3もしくはauthorNari/g1gc-impl-book - GitHubまでお願いします。

Webサイトのトップページ

(C) 2011-2012 Narihiro Nakamura