java-クラスのロードとガベージコレクションの監視


アプリケーションを起動したときに、どのクラスがどこからロードされたか、ガ ベージコレクションがいつ実行され、その処理にどのくらいの時間がかかったか を知りたいと思ったことはありますか。java コマンド行ツールのいくつかのコマ ンド行オプションを使用すると、これらの答えを知ることができます。

すでにご存じだと思いますが、java コマンド行ツール では -cp、-Xms、-Xmx と いった多数のコマンド行オプションを使用できます。-cp オプションはクラスパ スを指定するために、-Xms オプションと -Xmx オプションはヒープサイズを指定 するために使用します。たとえば、CLASSPATH 環境変数を設定する代わりに -cp

オプションを使用して、必要なクラスファイルの検出先のディレクトリを指定す

ることができます。

java -cp ExampleDir MyExample

この例では、MyExample?.class ファイルや、システムクラス以外の必要なファイ ルが ExampleDir? サブディレクトリから検出されます。このコマンド行の Examp leDir は、これらのファイルを ExampleDir? ディレクトリからだけ検出すること を意味しています (それが親ディレクトリの場合)。MyExample?.class が現在の作 業ディレクトリに含まれている場合、そのファイルは検出されません。

これらのオプションに比べるとあまり使われませんが、クラスのロードやガベー ジコレクションについて報告するオプションが 2 つあります。その一方、-verb ose:class オプションは、クラスが Java 仮想マシンにいつ、どこからロードさ れたかを報告します。たとえば、-verbose:class オプションを指定して、J2SE 1.4.2 SDK に付属している SwingSet2 デモプログラムをロードすると、このプロ グラムの構成要素としてロードされる多数のクラスについてのレポートが表示さ れます。次の 2 行はこのレポートからの抜粋です。

java -verbose:class -jar

  
C:\j2sdk1.4.2\demo\jfc\SwingSet2\SwingSet2.jar   

[Loaded FilePreviewer?] [Loaded javax.swing.plaf.TableUI from

  

C:\j2sdk1.4.2\jre\lib\rt.jar]

最初の行は、デモプログラム用にメイン JAR ファイルからクラスがロードされた ことを示しています (このプログラムを java -jar SwingSet2.jar というコマン ドで起動した場合)。2 番目の行は、TableUI クラスが c:\j2sdk1.4.2\jre ディ レクトリにある、ランタイムに付属している rt.jar ファイルからロードされた ことを示しています。Java プラットフォームの実装によって、レポートの表示形 式が異なる場合がありますが、クラスがロードまたはアンロードされるたびにメ ッセージが表示される点は同じです。

次の単純なプログラムを使用して、いくつのクラスが必要で、それらのクラスが いつロードされるかを調べてみましょう。

   public class Sample {
     public static void main(String args[]) {
       System.out.println("Hello, World");
     }
   }

Sample クラスをコンパイルし、-verbose:class オプションを指定して実行しま す。

  java -verbose:class Sample

このコマンドを実行すると、この単純なプログラムでは 5 つの jar ファイル ( rt.jar など) を開く必要があり、約 250 のクラスをロードする必要があること がわかります。

クラスがアンロードされたときにもメッセージが出力されます。その例として、 2003 年 8 月 19 日の記事「Unloading and Reloading Classes」で紹介した Ru nItReload? クラスを、-verbose:class コマンド行オプションを付けて実行してみ てください。

  • verbose:gc オプションは、ガベージコレクションの各イベントについての情報 を報告します。この情報の中には、ガベージコレクションの実行時間と、その前 後のヒープサイズが含まれています。このレポートの例を次に示します。
 [GC 27872K->26296K(42216K), 0.0069590 secs]
 [GC 28973K->26455K(42216K), 0.0036812 secs]
 [GC 29134K->26474K(42216K), 0.0016388 secs] 
[GC 29117K->26487K(42216K), 0.0008859 secs]
 [GC 29134K->26498K(42216K), 0.0009197 secs]
 [GC 29180K->26479K(42216K), 0.0008711 secs]
 [GC 29149K->26484K(42216K), 0.0008716 secs]
  • verbose:class の出力と同様に、出力形式についての決まりはなく、別の形式に 予告なく変更される場合があります。先頭の「GC」は、実行されたコレクション の種類を示しています。「->」の前の数値はコレクション前のヒープ消費量、「
  • >」の後の数値はコレクション後のヒープ消費量です。括弧の中の数値は、現在 割り当てられているヒープ容量です。秒数はコレクションの実行にかかった時間 です。

これらの情報はデバッグに役立ちます。たとえば、これらの情報を参照すると、 ガベージコレクションがクリティカルなタイミングで発生していないかどうか、 ガベージコレクションによってプログラムが異常終了しないかどうかを確認でき ます。JNI によって Java コードと C/C++ コードを組み合わせている場合、特に その C/C++ コードの側にバグがある場合、このような現象が起きることがありま す。

アプリケーションの起動に時間がかかり、その理由を知りたい場合、あるいは処 理の途中でガベージコレクションが発生し、それが問題の原因になっている場合、 これらのコマンド行オプションを試してみてください。

これらのコマンド行オプションやその他のコマンド行オプションの詳細について は、該当するプラットフォームの java コマンドのマニュアルを参照してくださ い。