31.6. JBoss Enterprise Application Platform のチューニング

本書の「はじめに」の項に記載されているコンポーネントを理解してから JBoss Enterprise Application Platform をチューニングするようにしてください。 また、 サーバー上でアプリケーションが使用するサービスについて理解してからそれらのサービスをチューニングしてパフォーマンスを向上するようにしてください。 また、 アプリケーションが使用する最適化されたデータベース接続を確立し、 これらの接続をサーバー上に設定することが重要となります。 本項では、 JBoss Enterprise Application Platform のパフォーマンスチューニングについて説明します。

31.6.1. メモリ使用率

JBoss Enterprise Application Platform を含む Java アプリケーションのメモリ使用率は割り当てられるヒープ領域によって決まります。 例えば、 現在割り当てられている 1GB のヒープ領域を 800MB に縮小するとメモリフットプリントが縮小されます (十分なヘッドルームがある場合)。
JVM (Java Virtual Machine: Java 仮想マシン) はメモリのセグメント (生成) を管理します。 ヒープ領域のセグメントを使い果たしてしまうと、 Java OutOfMemoryError (OOME) が表示されます。 Java OutOfMemoryError が発生する時、 すべてのベットが無効になります。 不良なステートを修正するにはアプリケーションを再起動する必要があります。 チューニングの一部として、 負荷下におけるメモリヘッドルームの大きさを確認します。 使用可能なメモリが少なすぎると、 最大 Java メモリサイズを大きくする必要があります (必要な場合は 64 ビット JVM へ変換)。
メモリ不足は例外ではなくエラーであるため、メモリ不足が発生するとエラーが生成されますがjava キャッチブロックでマスクされる可能性の低くなっています。ヒープ自体の一部でない永久メモリを使い果たしてしまうと OOME もスローされます。これは、ロードされたクラスの情報が維持される JVM 固有のメモリ領域です。クラスが大量にあると (大量の EJB ページや JSP ページなど) この領域をすぐ使い果う可能性があります。多くの場合、 アプリケーションのデプロイや再デプロイに失敗します。下記のように永久モリ領域を増やし、OOME が発生しないようにします。-server スイッチのデフォルトは 64 メガバイトです。
-XX:MaxPermSize=256m
これは、 ヒープへ追加される分となります。 この例の場合、 ヒープは 512M、 永久的な領域は 256M、 合計 768 メガバイトになります。 JVM 自体がシステムメモリの領域を多く使用し、 スレッドごとのスタック領域 (大きさは OS による) もあることを念頭に置いてください。 これらが HTTP/S プロセッサに加算されます。
-XX:MaxPermSize?=256m -Xmx512m (システムから割り当てられた合計768 メガバイトです。 VM の合計サイズではなく、 VM が 「C ヒープ」 やスタック領域に割り当てる領域は含まれていません。)
HotSpot Java 仮想マシンは、 アプリケーションのチューニングに使用するガベージコレクションの情報を収集するため使用できるさまざまなガベージコレクションツールによって構成されています。 HotSpot 仮想マシンについての詳細は、 http://java.sun.com/javase/technologies/hotspot/ を参照してください。
Java 6 には、 Java アプリケーションを監視できるようにする新しいツールが含まれています。 Jmap は、 Eclipse メモリアナライザーツール (http://www.eclipse.org/mat/) によって簡単に読み取れるヒープダンプファイル (http://java.sun.com/javase/6/docs/technotes/tools/share/jmap.html) を生成します。 jstat ツール (http://java.sun.com/javase/6/docs/technotes/tools/share/jstat.html) は、 Java メモリヒープの永続メモリ領域や他のセグメントの正確な状態を確認できるようにします。

31.6.1.1. VFS チューニング

VFS (仮想ファイルシステム: Vitrual File System) のさまざまなチューニングオプションを検索する際、 存在するほとんどの情報は VFSUtils クラスにあります。 このストリング定数は、 VFS 動作の設定に使用できる異なるシステムプロパティ設定を示します。
  • jboss.vfs.forceCopy
    ネストされた jar の処理方法を定義します。forceCopy が true の場合 (デフォルト)、ネストされた jar の一時コピーを作成し、それに応じて VFS を再配線します。forceCopy が false の場合、 メモリ内でネストされた jar を処理します。 この場合、一時コピーは作成されませんが、より多くのメモリが消費されます。
  • jboss.vfs.forceNoReaper は true と false のオプションがあり、デフォルトは false になります。
    パフォーマンスを向上するため、 別の reaper スレッドより非同期的に JAR ファイルを閉じます。 JAR ファイルを同期的に閉じたい場合は、 reaper スレッドを使用しないよう強制することができます。 URI クエリと noReaper クエリセクションを使用して定義することもできます。
  • jboss.vfs.forceCaseSensitive は true と false のオプションがあり、デフォルトは false になります。
    有効にすると、 ファイルパスの小文字と大文字を区別するよう強制できます。
  • jboss.vfs.optimizeForMemory は true と false のオプションがあり、デフォルトは false になります。
    有効にすると、 メモリ内の JAR 処理を再命令するため、 メモリ消費が増加します。
  • 既存の一時ファイルを再使用するため (展開やワイヤリングを再実行しないようにするため) jboss.vfs.cache (org.jboss.virtual.spi.cache.helpers.NoopVFSCache) クラスを定義することができます。 VFS レジストリはこのクラスの定義を使用して既存の VFS ルートを維持します。
    VFS クラスからの VirtualFile ルックアップはこの singleton キャッシュインスタンスを使用して既存の一致するキャッシュエントリを確認します。 一致することで、 VirtualFile インスタンスの展開に使用できる既存の「先祖」も考慮します。
31.6.1.1.1. VFS キャッシュのチューニング
前述の通り、 VFS キャッシュが VFS ルートを保持し、 VFS ルートより VirtualFile ルックアップが既存の VirtualFile インスタンスにアクセスできます。 これは、 特に一時ファイル (ネストされた JAR より作成) の場合に便利で、 ネストされた JAR ファイルに関連するリソースの解凍を複数回実行する必要がありません。
VFS では org.jboss.virtual.spi.cache.helpers.NoopVFSCache が使用されるため、 デフォルトではキャッシングは関係ありませんが、 独自の実装を提供するか、既存の VFS 実装を選択することができます。
org.jboss.virtual.plugins.cache パッケージのキャッシュ実装は次の通りです。
  • SoftRefVFSCache: マップのエントリ値としてソフト参照を使用します。
  • WeakRefVFSCache: マップのエントリ値として弱参照を使用します。
  • TimedVFSCache: defaultLifetime 後にキャッシュエントリをエビクトします。
  • LRUVFSCache: LRU を基にキャッシュエントリをエビクトし 最小エントリと最大エントリを維持します。
  • CombinedVFSCache: 少数の永久ルートを保持し、 他の新しいルートは realCache プロパティにキャッシュされます。
JBoss Enterprise Application Platform では、 監視し維持する永久ルートを認識するため CombinedVFSCache を使用します。 MC の Bean 設定ファイルで設定する方法は次の通りです。
   <bean name="VFSCache">
     <constructor factoryClass="org.jboss.virtual.spi.cache.VFSCacheFactory" factoryMethod="getInstance">
       <!-- Use the CombinedVFSCache implementation -->
       <parameter>org.jboss.virtual.plugins.cache.CombinedVFSCache</parameter>
     </constructor>
     <start ignored="true"/>
     <property name="permanentRoots">
       <map keyClass="java.net.URL" valueClass="org.jboss.virtual.spi.ExceptionHandler">
         <entry>
           <key>${jboss.lib.url}</key>
           <value><null/></value>
         </entry>
         <entry>
           <key>${jboss.common.lib.url}</key>
           <value><inject bean="VfsNamesExceptionHandler"/></value>
         </entry>
         <entry>
           <key>${jboss.server.lib.url}</key>
           <value><inject bean="VfsNamesExceptionHandler"/></value>
         </entry>
         <entry>
           <key>${jboss.server.home.url}deploy</key>
           <value><inject bean="VfsNamesExceptionHandler"/></value>
         </entry>
       </map>
     </property>
     <property name="realCache">
       <bean class="org.jboss.virtual.plugins.cache.IterableTimedVFSCache"/>
     </property>
   </bean>
新しいカスタム VFS ルート (追加の deploy ディレクトリなど) はこの設定に追加しなければなりません。
31.6.1.1.2. アノテーションスキャンのチューニング
現在、 リソースのスキャンを制限する方法は 3 つあります。
  • XML またはプログラムにて ScanningMetaData を提供します。
  • deployers/metadata-deployer-jboss-beansGenScanDeployer Bean に新しいデプロイメントフィルターを追加します。
  • deployers/metadata-deployer-jboss-beansJBossCustomDeployDUFilter を変更します。
ScanningMetaData は META-INF ディレクトリにある jboss-scanning.xml ファイルから取得することもできます。 このファイルの簡単な例は次の通りです。
<scanning xmlns="urn:jboss:scanning:1.0">
  <path name="myejbs.jar">
    <include name="com.acme.foo"/>
    <exclude name="com.acme.foo.bar"/>
  </path>
  <path name="my.war/WEB-INF/classes">
    <include name="com.acme.foo"/>
  </path>
</scanning>
この例では、 デプロイメント内にパスをリストし、 包含または除外するパッケージをリストします。 明示的な包含がない場合は、 除外されていないパッケージがすべて包含されます。 パス要素がない場合は、 次の例のようにすべてのパスが含まれます。
<scanning xmlns="urn:jboss:scanning:1.0">
<!-- Purpose: Disable scanning for annotations in contained deployment. -->
</scanning>
jboss-classloading.xml ファイルに適切なメタデータを提供しスキャンを制限する方法もあります。詳細は、 『JBoss Microcontainer User Guide』 のクラスローディング層の章を参照してください。