kagamihogeの日記

kagamihogeの日記です。

JEP 122: Remove the Permanent Generationをテキトーに訳した

http://openjdk.java.net/jeps/122 のテキトーな訳。

某所のMLでこれ読めやってのが上がってたんで、Sorry japanese Engineer(SE)な俺としては、きんモザで英語の勉強に目覚めた(大嘘)のでイマサラ感あふれるものの読むことにした。

JEP 122: Permanent領域の削除(Remove the Permanent Generation)

Summary

Hotspot JVMからPermanent領域を削除するため、Permanent領域のサイズを調整する必要があります。

Non-Goals

アプリケーションクラスのClass Data Sharingの拡張。クラスメタデータに必要となるメモリの縮小。クラスメタデータの非同期コレクション化。

Success Metrics

クラスメタデータ、interned Strings*1、クラスのstatic変数はpermanent領域からJavaヒープかネイティブメモリのどちらかに移動されます。

Hotspot JVMにおけるpermanent領域のコードは削除されます。

アプリケーションのスタートアップとフットプリントは、未計測のベンチマークでも1%以上縮小することはありません。

Motivation

JRockitとHotspotを収束する取り組みの一環です。JRockitの使用者はpermanent領域の調整を必要としていない(JRockitはpermanent領域が無いので)し、permanent領域を調整する習慣がありません。

Description

Hotspotのpermanent領域のコンテンツの一部をJavaヒープに移動し、残りをネイティブメモリに移します。

JavaクラスのHotspotの表現(ここではクラスメタデータ)は、現在はpermanent領域と呼ばれるJavaヒープに格納されています。加えてinterned Stringsとクラスstatic変数はpermanent領域に格納されています。

permanent領域はHotspotによって管理されており、この領域は、すべてのクラスメタデータJavaアプリケーションによって使用されるクラスstatic変数・interned Stringsのために、十分な領域を持たなければなりません。クラスメタデータとstatic変数は、あるクラスがロードされる時にpermanent領域に割り当てられ、クラスがアンロードされる時にpermanent領域からGCされます。Interned Stringもまたpermanent領域がGCされるときにGCされます。

この実装案は、クラスメタデータをネイティブメモリに割り当てて、interned Stringsとクラスstatic変数をJavaヒープに移動します。Hotspotはクラスメタデータ用のネイティブメモリの明確な割り当てと解放を行います。新しいクラスメタデータの割り当ては、デフォルトないしコマンドラインで指定する-XX:MaxPermSizeの設定値よりはむしろ、利用可能なネイティブメモリの総量に制限されます。

クラスメタデータ用のネイティブメモリの割り当ては、クラスメタデータの複数ピースを収めるのに十分な大きさのブロックで行われます。各ブロックはクラスローダーに関連付けされて、そのクラスローダーでロードされるすべてのクラスメタデータは、そのクラスローダー用のブロックから、Hotspotによって割り当てられます。必要に応じて、クラスローダーのための追加ブロックが割り当てられます。ブロックサイズはアプリケーションの振る舞いに依存して変化します。このサイズは、内部および外部のフラグメンテーションを制限するために、選択されます。クラスローダーに関連付いた全ブロックを解放することでクラスローダーが死ぬ時、クラスメタデータの領域は解放されます。クラスメタデータはクラスの生存期間中は移動されません。

Alternatives

permanent領域サイズ調整の必要性を無くすには、拡大可能なpermanent領域を持つことで満たせます。permanent領域を拡大させるための追加のデータ構造(card tableとblock offset tableのような)が必要と考えられます。効果的な実装のためには、permanent領域は使用できない幾つかの部分を一つの連続した領域として見る必要があります。

Testing

ネイティブメモリ使用量の変化は、メモリリーク調査テスト中はモニタする必要があります。

Risks and Assumptions

Hotspot JVMに対する変更範囲は第一級のリスクです。また、変更の必要が何なのかを正確に定義することは、実装中に決定されることでしょう。

この大規模なプロジェクトはすべてのガベージ・コレクターの広範囲に渡って影響を及ぼします。permanent領域の知識と動作はランタイムとHotspot JVMコンパイラ部分双方に存在します。ガベージ・コレクター外部のデータ構造は、ネイティブメモリのクラスメタデータのガベージ・コレクターの処理を容易にするために、変更されることがあります。

JVMの一部はこのプロジェクトによって再実装する必要があるでしょう。

例として、class data sharingは影響を受けるでしょうし、全体か部分的にか再実装が要求されるでしょう。

Class redefinitionもリスクの範囲です。Redefinitionは、permanent領域のガベージ・コレクション期間中の、クラスメタデータガベージコレクションに依存しています。(言い換えると、redefinitionは現在、redefinedなクラスを解放しないので、redefinedされたクラスのメタデータが解放されるとき、それを発見する方法が必要です)。

interned Stringsとクラスstatic変数のJavaヒープへの移動はOut-of-memory例外もしくはGC回数の増加を引き起こす可能性があります。ユーザによって幾つかの-Xmxを調整する必要が出てくるでしょう。

(permanent領域の)クラスメタデータへのポインタはUseCompressedOopsオプションを使用して、Javaヒープに対するポインタでも同様な方法で圧縮が可能です。これは有意なパフォーマンス向上をもたらします(数パーセントのオーダーで)。ネイティブメモリ中のメタデータへのポインタは、異なる実装なものの、同じような実装で圧縮されるでしょう。後者の実装はJavaヒープへのポインタ圧縮ほど高い性能にはならないでしょう。メタデータへのポインタ圧縮に対する要求は、メタデータのサイズ上限を課すことになります。たとえば、あるアドレス下(例えば4G制限)に割り当てるすべてのメタデータを要求される実装はメタデータのサイズ制限をすることになります。

Dependences

permanent領域に関するツールは再実装の必要があります。serviceability agent, jconsole, ava VisualVM, jhatなどのツールが影響を受けるでしょう。

Impact

  • 他のJDKコンポーネント:permanent領域に関するツール
  • 互換性(compatibility):permanent領域に関するコマンドラインフラグは廃止されるでしょう。
  • ドキュメント:permanent領域のリファレンスは削除される必要があるでしょう。

参考文献&URL

*1:"interned string" javaとかでぐぐる