連載
» 2005年04月02日 00時00分 公開

Javaパフォーマンスチューニング(3):Javaのヒープ・メモリ管理の仕組み (1/2)

[小林聡史,@IT]

本記事は、HP-UX Developer Edgeに掲載された記事を株式会社アットマーク・アイティおよび本記事の筆者が独自の判断のもとに加筆・修正したものです。


 今回は、Javaにおけるヒープ・メモリ管理の詳細を説明します。JVMのヒープ・メモリの中で、新しいオブジェクトと古いオブジェクトがどのように配置されるかを理解することで、ヒープ・メモリが有効に利用されているか否かを判断することができます。また、JVMが出力するガベージ・コレクションのログを解析し、オプションの指定によってヒープ・メモリのサイズを適切にチューニングする方法を紹介します。

Java ヒープ・メモリの構造

 Javaにおけるガベージ・コレクションのメカニズムを理解するには、まずヒープ・メモリの構造を知っておく必要があります。

図1 JVMヒープ・メモリの構造 図1 JVMヒープ・メモリの構造

 図1は、JVM におけるヒープ・メモリの構造を示したものです。この図が示すように、ヒープ・メモリの中には新しいオブジェクトを格納する「NEW」領域と、古いオブジェクトを格納する「OLD」領域が存在します。生まれてすぐに不要となる短命なオブジェクトはNEW領域でその一生を過ごし、長時間存在するオブジェクトはOLD領域に留まることになります。また、図1には示されていませんが、ヒープ・メモリにはJVMにロードされたクラスの置き場所として利用される「Permanent」領域も存在します。

 JVMでは、「Scavenge GC」と「Full GC」という2種類のガベージ・コレクションが実行されます。Scavenge GCはNEW領域のみを対象とした短時間で終了するガベージ・コレクションであり、頻繁に実施されます。一方、Full GCはNEWとOLD両方の領域を対象とした大がかりなガベージ・コレクションであり、比較的低い頻度で実施されます。こうした理由から、ヒープ・メモリ全体がオブジェクトの世代別に分割されています。

 JVMのデフォルト設定では、NEW領域の起動時のサイズが2MB、最大サイズが16MBにセットされています。また、OLD領域の起動時のサイズは4MB、最大サイズは48MBです。これらのサイズは、以下のJVMオプションを用いることで変更できます。

オプション名 内容
-Xms ヒープ・メモリ全体の起動時のサイズ
-Xmx ヒープ・メモリ全体の最大サイズ
-Xmn NEW領域のサイズ
-XX:SurvivorRatio= Eden領域のサイズをFromまたはTo領域のサイズで割った値(FromとTo領域は同じサイズ)

 ここで、最初の3種類のオプションについては、指定するサイズをメガバイト単位で指定します。例えば「-Xmn256m」は、NEW領域に256MBを割り当てることを意味します。これらのオプションの使用方法については、以下に詳しく説明します。

世代別ガベージ・コレクションのメカニズム

 図1に示されるとおり、NEW領域内はさらに「Eden」「From」「To」という3つの領域に分割されています。これらのうち、Eden領域は、新しいオブジェクトが作成された際に最初に配置されるメモリ領域です。よって同領域は、時間が経つとともに新しいオブジェクトで埋め尽くされていきます。

 Eden領域が満杯になると、前述したScavenge GCが実行されます。このとき、まだ使用中のオブジェクト(すなわち、他のオブジェクトから参照されているオブジェクト)についてはEden領域からTo領域へと移動され、参照されていない不要なオブジェクトは破棄されます。これにより、Eden領域全体がクリーンアップされ、再び新しいオブジェクトを受け入れ可能になります(図2)。

図2 Scavenge GCによるEden領域からTo領域へのオブジェクト移動 図2 Scavenge GCによるEden領域からTo領域へのオブジェクト移動

 ここで、図2のTo領域に移動されたオブジェクトに「1」という数値が振られていることに注目してください。これはScavenge GCによってオブジェクトが移動した回数を表しています。この数値の意味については追って説明します。

 続いて、Eden領域が再度満杯になり、2回目のScavenge GCが実行される状況を考えます。このとき、前回のGC時のFrom領域とTo領域は互いに入れ替わることになります。つまり、前回のGCでオブジェクトの移動先とされたTo領域は、次回のGCではFrom領域として扱われるわけです。そして、このFrom領域とEden領域にある使用中のオブジェクトが、再びTo領域に移動されます(図3)。

図3 2回目のScavenge GCによるオブジェクト移動 図3 2回目のScavenge GCによるオブジェクト移動

 このように、Scavenge GCでは、オブジェクトが不要になるまでの間、From領域とTo領域の間でオブジェクトの移動を繰り返します。そして、この移動の際には、オブジェクトに振られた移動回数の数値がカウントアップされます。図3を見れば、From領域からTo領域へ移動したオブジェクトの移動回数が「2」に増えていることお分かりいただけるでしょう。Scavenge GCでは、この移動回数が「MaxTenuringThreshold」と呼ばれるしきい値を上回るオブジェクトについて、OLD領域への移動を行います。

 JVMにおけるMaxTenuringThresholdのデフォルト値は32に設定されています。よって新しいオブジェクトは、最大で32回までScavenge GCの対象となり、その間をFrom領域とTo領域の中で過ごします。この回数を超えて生き延びたオブジェクトは、「寿命の長いオブジェクト(tenured object)」としてOLD領域に移動される仕組みです。

       1|2 次のページへ

Copyright© 2018 ITmedia, Inc. All Rights Reserved.

@IT Special

- PR -

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。