プライマリ・コンテンツに移動
Java Platform, Standard Edition HotSpot仮想マシン・ガベージ・コレクション・チューニング・ガイド
リリース10
E94983-01
目次へ移動
目次

前
前へ

11 その他の考慮事項

この項では、ガベージ・コレクションに影響するその他の状況について説明します。

ファイナライズと弱参照、ソフト参照およびファントム参照

一部のアプリケーションは、ファイナライズと弱参照、ソフト参照またはファントム参照を使用してガベージ・コレクションと相互作用します。

これらの機能は、Javaプログラミング言語のレベルでパフォーマンスに悪影響を与える可能性があります。たとえば、ファイナライズによってファイル記述子を閉じると、外部リソース(記述子)がガベージ・コレクションの機敏性に依存するようになります。ガベージ・コレクションにメモリー以外のリソースを管理させることは、通常はお薦めできません。

Javaファイナライズのメモリー保持問題の対処方法に関する項を参照してください。ここでは、ファイナライズの問題とこれを回避する技術について詳細に説明しています。

明示的なガベージ・コレクション

アプリケーションがガベージ・コレクションと相互作用できるもう1つの方法は、System.gc()を使用して、すべてのガベージ・コレクションを明示的に呼び出す方法です。

これを行うと、必要ない場合(たとえば、マイナー・コレクションで十分な場合)でもメジャー・コレクションの実行が強制されるので、通常は使用しないことをお薦めします。明示的なガベージ・コレクションによるパフォーマンスへの影響を測定するには、フラグ-XX:+DisableExplicitGCを使用してVMにSystem.gc()のコールを無視させ、明示的なガベージ・コレクションを無効にします。

明示的なガベージ・コレクションが最もよく使用される例の1つが、リモート・メソッド呼出し(RMI)の分散ガベージ・コレクション(DGC)です。RMIを使用するアプリケーションは、他の仮想マシンのオブジェクトを参照します。これらの分散アプリケーションでは、ローカル・ヒープのガベージ・コレクションを時々呼び出さないとガベージを収集できないので、RMIがフル・コレクションを定期的に実行します。これらのコレクションの実行間隔はプロパティで制御できます(次の例を参照)。

java -Dsun.rmi.dgc.client.gcInterval=3600000
    -Dsun.rmi.dgc.server.gcInterval=3600000 ...

この例では、明示的なガベージ・コレクションの実行間隔をデフォルトの1回/分ではなく、1回/時間に指定します。ただし、これでも一部のオブジェクトが回収されるまでに長時間かかる場合があります。DGCのタイムリな処理に上限を設定する必要なければ、これらのプロパティの値をLong.MAX_VALUEまで引き上げ、明示的なコレクションの時間間隔を事実上無限大にすることができます。

ソフト参照

サーバー仮想マシンでは、ソフト参照がクライアント仮想マシンよりも長くライブに保たれます。

クリア間隔を制御するには、コマンド行オプション-XX:SoftRefLRUPolicyMSPerMB=<N>を使用して、ソフト参照を(強到達可能ではなくなってから)ライブに保つ期間を、ヒープ内の空き領域1MB当たりのミリ秒(ms)で指定します。デフォルト値は1000ms/MBで、これは、(オブジェクトへの最後の強参照が収集された後の)ソフト参照がヒープ内の空き領域1MB当たり1秒の寿命であることを意味します。ソフト参照は、散発的に発生するガベージ・コレクション時にのみクリアされるので、これは概算値です。

クラス・メタデータ

JavaクラスにはJava Hotspot VM内の内部表現があり、それはクラス・メタデータと呼ばれます。

以前のリリースのJava Hotspot VMで、クラス・メタデータはPermanentと呼ばれる永続的世代に割り当てられていました。JDK 8以降、永続的(Permanent)世代が削除され、クラス・メタデータがネイティブ・メモリーに割り当てられます。クラス・メタデータに使用できるネイティブ・メモリーの容量はデフォルトで無制限です。クラス・メタデータに使用するネイティブ・メモリーの容量に上限を設定するには、オプション-XX:MaxMetaspaceSizeを使用します。

Java Hotspot VMではメタデータ用の領域を明示的に管理します。OSから領域が要求され、その領域がチャンクに分割されます。そのチャンクからクラス・ローダーがメタデータに領域を割り当てます(チャンクは特定のクラス・ローダーにバインドされます)。クラス・ローダーのクラスがアンロードされると、そのチャンクは再利用に回されるか、OSに返されます。メタデータは、mallocではなくmmapによって割り当てられた領域を使用します。

-XX:UseCompressedOopsをオンにして-XX:UseCompressedClassesPointersを使用する場合、ネイティブ・メモリーの論理的に異なる2つの領域がクラス・メタデータに使用されます。-XX:UseCompressedClassPointersは、Javaオブジェクト参照の場合の-XX:UseCompressedOopsと同様に、32ビットのオフセットを使用してクラス・ポインタを64ビットプロセスで表現します。このような圧縮クラス・ポインタにリージョンが割り当てられます(32ビット・オフセット)。リージョンのサイズは-XX:CompressedClassSpaceSizeで設定でき、デフォルトは1ギガバイト(GB)です。圧縮クラス・ポインタの領域は、初期化時に-XX:mmapによって割り当てられた領域として確保され、必要に応じてコミットされます。-XX:MaxMetaspaceSizeは、コミットされた圧縮クラスの領域と他のクラス・メタデータの領域の合計に適用されます。

クラス・メタデータは対応するJavaクラスのアンロード時に割当て解除されます。Javaクラスはガベージ・コレクションに伴ってアンロードされるので、クラスのアンロードとクラス・メタデータの割当て解除を行うためにガベージ・コレクションが誘発される場合があります。クラス・メタデータ用にコミットされた領域が一定のレベル(最高水位標)に到達すると、ガベージ・コレクションが発生します。ガベージ・コレクション後、クラス・メタデータから解放された領域量に応じて、最高水位標が上げられたり、下げられたりすることがあります。別のガベージ・コレクションがすぐに発生しないように、最高水位標は上げられます。最高水位標の初期値は、コマンド行オプション-XX:MetaspaceSizeの値に設定されます。-XX:MaxMetaspaceFreeRatioオプションと-XX:MinMetaspaceFreeRatioオプションを基に、これを上げ/下げします。クラス・メタデータで使用可能なコミットされた領域(クラス・メタデータ用にコミットされた総領域の割合)が-XX:MaxMetaspaceFreeRatioより大きいと、最高水位標は下げられます。これが-XX:MinMetaspaceFreeRatioより低いと、最高水位標は上げられます。

クラス・メタデータによるガベージ・コレクションの早期誘発を避けるには、オプション-XX:MetaspaceSizeに高めの値を指定します。アプリケーションに割り当てられるクラス・メタデータの容量はアプリケーションに依存するので、 -XX:MetaspaceSizeの選択に一般的なガイドラインはありません。-XX:MetaspaceSizeのデフォルト・サイズは、12MBから約20MBの範囲でプラットフォームに依存します。

メタデータに使用される領域に関する情報はヒープの出力に含まれます。出力は、通常次のようになります。

[0,296s][info][gc,heap,exit] Heap
[0,296s][info][gc,heap,exit] garbage-first heap total 514048K, used 0K [0x00000005ca600000, 0x00000005ca8007d8, 0x00000007c0000000)
[0,296s][info][gc,heap,exit] region size 2048K, 1 young (2048K), 0 survivors (0K)
[0,296s][info][gc,heap,exit] Metaspace used 2575K, capacity 4480K, committed 4480K, reserved 1056768K
[0,296s][info][gc,heap,exit] class space used 238K, capacity 384K, committed 384K, reserved 1048576K

Metaspace」で始まる行のused値は、ロード済クラスが使用している領域量です。capacity値は、現在割り当てられているチャンク内のメタデータで使用可能な領域です。committed値は、チャンクの使用可能な領域量です。reserved値は、メタデータ用に確保された(必ずしもコミットされているとはかぎらない)領域量です。class spaceで始まる行には、圧縮クラス・ポインタのメタデータの対応する値が含まれています。