7.12 明示管理ヒープの自動配置機能を使用したExplicitヒープの利用の検討

ここでは,明示管理ヒープの自動配置機能を使用したExplicitヒープの利用の検討について説明します。

明示管理ヒープ機能を使用してExplicitヒープ領域を利用する際,自動配置機能を使用することで,明示管理ヒープ機能を容易に使用することができます。また,次に示すような場合は,自動配置機能を使用することをお勧めします。

<この節の構成>
(1) アプリケーション内にTenured領域の増加原因のオブジェクトがある場合
(2) 特定のフレームワークを使用している場合
(3) Tenured領域利用済みサイズの増加原因が不明な場合

(1) アプリケーション内にTenured領域の増加原因のオブジェクトがある場合

アプリケーション内にTenured領域の増加原因のオブジェクトがある場合,自動配置設定ファイルを使用してオブジェクトをExplicitヒープに配置することをお勧めします。オブジェクトの配置を検討した方がよいJavaプログラムの例を次に示します。

01:package abcd.efg;
02:import java.util.HashMap;
03:// KVStorageのインスタンスは,長期間生存し続ける
04:class KVStorage {
05:  HashMap _map = new HashMap();
06:  
07:  public void store(MyKey k,MyData d) {
08:    // ...前処理...
09:    _map.put(k,d);
10:    // ...後処理...
11:  }
12:
13:  public MyData load(MyKey k) {
14:    // ...前処理...
15:    MyData d = map.get(k);
16:    // ...後処理...
17:    return d;
18:  }
19:}

この設定例の場合,KVStorageがインスタンスフィールドに保持しているHashMapクラスがTenured領域のメモリサイズ増加の要因となる長寿命オブジェクトとなります。このオブジェクトの生成先をExplicitヒープへ変更する場合,次の例のように自動配置設定ファイルを指定します。

# 生成個所(メソッド名やクラス名), 生成するクラス名 の対で記載。
abcd.efg.KVStorage.<init>, java.util.HashMap

この例のように自動配置設定ファイルを指定することで,Javaプログラムの例の5行目のHashMapインスタンス(_map)の生成先がJavaヒープからExplicitヒープに変更されます。また,storeメソッドで_mapに格納したMyKeyのインスタンス,およびMyDataのインスタンスも,順次Explicitヒープに移動されます。これらのインスタンスは,不要となった時点でJavaVMによって自動的に解放されます。

(2) 特定のフレームワークを使用している場合

アプリケーションサーバとHibernateの両方を動作させた場合,Tenured領域の増加の要因となるオブジェクトがあります。アプリケーションサーバでは,これらオブジェクト向けの明示管理ヒープ自動配置設定を内部に保持しています。この設定は,Explicitメモリブロックの自動配置機能を有効にする(-XX:+HitachiAutoExplicitMemoryオプションを指定)だけで有効となります。

Hibernateへのクエリ結果を長期間保持するようなアプリケーションの場合,次に示す内容を自動配置設定ファイルに指定することで,Tenured領域の増加を抑止できることがあります。

org.hibernate.impl.AbstractSessionImpl.createQuery(java.lang.String), org.hibernate.impl.QueryImpl

org.hibernate.engine.query.HQLQueryPlan.performList(org.hibernate.engine.QueryParameters, org.hibernate.engine.SessionImplementor), java.util.ArrayList

org.hibernate.engine.query.HQLQueryPlan.performList(org.hibernate.engine.QueryParameters, org.hibernate.engine.SessionImplementor), org.hibernate.util.IdentitySet

なお,アプリケーションサーバとHibernateとの接続確認には,Hibernate Core 3.2.6 GAを使用しています。また,Explicitメモリブロックの自動配置機能によって,クラスローディング時間が増加し,その結果JavaVMの起動時間や,アプリケーションサーバでのアプリケーションのデプロイ時間が増加するおそれがあります。

(3) Tenured領域利用済みサイズの増加原因が不明な場合

Survivor領域のチューニングを実施しても,Tenured領域利用済みサイズが増加し,それによるフルガーベージコレクションの発生間隔がシステムの要件を満たせない場合,Tenured領域利用済みサイズの増加原因となるオブジェクトをExplicitヒープへ生成します。Explicitヒープへオブジェクトを生成するには,明示管理ヒープの自動配置設定ファイルを設定します。

Tenured領域利用済みサイズの増加原因となるオブジェクトを調査する方法,および自動配置設定ファイルの設定方法について説明します。

(a) Tenured領域利用済みサイズ増加の調査

実行中のアプリケーションに対して,jheapprofコマンドに-garbageオプションを指定し,Tenured領域内不要オブジェクト統計機能を実行します。

なお,08-70よりも前のバージョンを使用している場合,Explicitメモリブロックの自動配置機能(-XX:+HitachiAutoExplicitMemory)と同時に-garbageオプションを利用するときには,あらかじめ-XX:-HitachiExplicitMemoryPartialTenuredAreaCollectionオプションを指定した状態で,アプリケーションサーバを起動してください。

Tenured領域内不要オブジェクト統計機能の出力例を次に示します。これによって,Tenured領域利用済みサイズ増加の原因となっているオブジェクト(Tenured増加要因の基点オブジェクト)のクラス名のリストがスレッドダンプログファイルに出力されます。

Garbage Profile Root Object Information
-----------------------------------
*, java.util.HashMap # 35234568
*, java.util.WeakHashMap # 4321000

この出力例では,Tenured領域利用済みサイズの増加原因として,java.util.HashMapのオブジェクトが35,234,568バイト,またjava.util.WeakHashMapのオブジェクトが4,321,000バイトであることがわかります。Tenured領域内不要オブジェクト統計機能の詳細については,マニュアル「Cosminexus アプリケーションサーバ 機能解説 保守/移行/互換編」の「8.8 Tenured領域内不要オブジェクト統計機能」を参照してください。

(b) 自動配置設定ファイルへの記載

Tenured領域内不要オブジェクト統計機能の出力例のリスト部分(後半2行)を,自動配置設定ファイルへ入力します。自動配置設定ファイルの設定例を示します。

*, java.util.HashMap # 35234568
*, java.util.WeakHashMap # 4321000

この場合,プログラム中のすべてのjava.util.HashMapオブジェクト,およびjava.util.WeakHashMapオブジェクトはExplicitヒープに生成されます。

また,これらのオブジェクトに格納したオブジェクトも順次Explicitヒープに移動します。しかし,Explicitヒープへのオブジェクトの生成は,Javaヒープへのオブジェクトの生成よりも実行時にオーバーヘッドが掛かります。このため,オブジェクトの生成個所を絞り込むことで,実行時のオーバーヘッドを削減できます。

自動配置設定ファイルでは,「*」は「JavaVM上で動作するすべてのクラス」を意味します。この設定例の場合,すべてのクラスでのjava.util.HashMapおよびjava.util.WeakHashMapのオブジェクトの生成先がExplicitヒープになります。これによって,実際にはTenured利用済みサイズ増加の原因ではないオブジェクトの生成先もExplicitヒープとなり,オーバーヘッドが増加するおそれがあります。

「*」を指定したことによって,アプリケーションのスループットが要件を満たせなくなった場合は,Tenured領域利用済みサイズ増加の原因となっているオブジェクトの生成個所を絞り込むことを検討してください。

システム運用者とアプリケーション開発者が異なる場合は,アプリケーション開発者への調査の依頼が必要です。アプリケーションの詳細な調査が困難な場合でも,自動配置設定ファイルでは生成個所を「すべてのクラス」,「特定のパッケージ」,「特定のクラス」,および「特定のメソッド」の4段階の粒度でオブジェクトの生成個所を指定できます。そのため,調査可能な範囲で絞り込みを実施して,自動配置設定ファイルを指定することによって,スループットが向上する場合もあります。

例えば,生成個所が「com.abc.defg」パッケージ下の場合,自動配置設定ファイルの設定例を次のように変更することによって,「すべてのパッケージのすべてのクラス」から,「com.abc.defgパッケージおよびサブパッケージのすべてのクラス」まで絞り込みができます。

com.abc.defg.*, java.util.HashMap # 35234568
com.abc.defg.*, java.util.WeakHashMap # 4321000

自動配置設定ファイルの指定方法の詳細については,マニュアル「Cosminexus アプリケーションサーバ 機能解説 拡張編」の「8.11.2 自動配置設定ファイルを使った明示管理ヒープ機能の使用」を参照してください。

(c) Tenured領域内不要オブジェクト統計機能によるアプリケーションの調査

自動配置設定ファイルの内容を基に,アプリケーションを調査する場合に,Tenured領域内不要オブジェクト統計機能を利用します。

jheapprofコマンドに-garbageオプションを指定し,Tenured領域内不要オブジェクト統計機能を実行することで,Tenured増加要因の基点オブジェクトリスト,およびTenured領域内不要オブジェクトの統計情報を拡張スレッドダンプに出力します。拡張スレッドダンプの出力例を次に示します。

Garbage Profile
---------------
________________Size__Instances__Class________________
           35234568      10648 java.util.HashMap
            5678900      10668 [Ljava.util.HashMap$Entry;
            4456788       7436 java.util.HashMap$Entry
            4321000        200 java.util.WeakHashMap
            1234568        190 [Ljava.util.WeakHashMap$Entry
1456788       9524 java.lang.String
1256788       6424 com.abc.defg.MyData;

Tenured領域内不要オブジェクト統計機能では,Tenured増加要因の基点オブジェクトリストには出力されない,java.util.HashMapやjava.util.WeakHashMapに格納されているオブジェクトも出力されます。また,各オブジェクトのインスタンス数も出力されます。

さらに,このログを複数回取得して,クラス別統計情報解析機能(jheapprofanalyzerコマンド)の入力ファイルとすることで,各オブジェクトサイズ,およびインスタンス数の時間の変化を調査することができます。

これらの情報を基に,アプリケーションを調査してオブジェクト生成個所の絞り込みをします。Tenured領域内不要オブジェクト統計機能の詳細については,マニュアル「Cosminexus アプリケーションサーバ 機能解説 保守/移行/互換編」の「8.8 Tenured領域内不要オブジェクト統計機能」を参照してください。クラス別統計情報解析機能の詳細については,マニュアル「Cosminexus アプリケーションサーバ 機能解説 保守/移行/互換編」の「8.10 クラス別統計情報解析機能」を参照してください。