この章では、JRockit JVMの起動が遅い原因となっている問題の、診断およびトラブルシューティングに役立つ情報を提供します。
この章の内容は以下のとおりです。
アプリケーションの起動時に動作が遅くなる問題には次の原因が考えられます。
アプリケーションがファイルのインポートを待機している可能性があります。
大量のメソッドのコンパイルが必要である可能性があります。
コード最適化に問題がある可能性があります(特にシングルCPUマシンの場合)。
JVMではなくJavaアプリケーションによって引き起こされた可能性があります。
開発用のサードパーティのJVMから、本番用のJVMとしてJRockit JVMに最近移行した場合。
JRockit JVMは、長時間実行されるアプリケーション用に設計されているJITコンパイルJVMです。このJVMは、メソッドが初めてコールされたときにそのメソッドをマシン・コードにコンパイルします。したがって、多数の新規メソッドがコンパイルされるためにアプリケーションの起動は比較的に遅くなります。ただし、起動した後は、アプリケーションの実行速度は速くなります。さらに、アプリケーションの実行にしたがって、JVMは頻繁にコールされるメソッドを最適化して、パフォーマンスをさらに向上させます。
起動時にJVMが大量のメソッドをコンパイルしているかどうかを確認するには、-Xverbose:codegen
オプションを使用します。このオプションを使用すると、コンパイル中のメソッドに関する次の情報が表示されます。
メソッドの名前
メモリーの場所
コンパイル・プロセスの持続時間
アプリケーションで開始されたときからのコードのコンパイルの合計経過時間
-Xverbose:codegen
オプションの出力の例を次に示します。
[INFO ][codegen][00004] #23 (Normal) java/lang/Object.registerNatives()V [INFO ][codegen][00004] #23 0.113-0.114 0x0000000100011B60-0x0000000100011C6B 0.80 ms 128KB 0 bc/s (11.60 ms 63252 bc/s) [INFO ][codegen][00004] #24 (Normal) java/lang/OutOfMemoryError.<init>(Ljava/lang/String;)V [INFO ][codegen][00004] #24 0.115-0.115 0x0000000100011C80-0x0000000100011C92 0.38 ms 64KB 15662 bc/s (11.99 ms 61731 bc/s
JITコンパイルが完了した後、アプリケーションは起動時よりも早く実行されます。メソッドが引き続きコールされるとJVMではプリコンパイルされたコードが実行されるためです。
メソッドの最適化にかかった時間を確認するには、-Xverbose:opt
オプションを使用します。
アプリケーションがデータ・ファイルを検索したり、データベース内のデータを調べたりする場合なども、起動が遅くなることがあります。
起動が遅い原因がアプリケーションにあると思われる場合は、フライト・レコーダ・ツールを使用してアプリケーション・データを記録および分析します。
フライト・レコーダ・ツールの詳細は、『Oracle JRockitフライト・レコーダ・ラン・タイム・ガイド』を参照してください。
アプリケーションの内部のタイミングは、System.nanoTime()
およびSystem.currentTimeMillis()
の各メソッドを挿入することで測定できます。これらのメソッドは実行時に追加的なリソースを消費することになりますが、パフォーマンスへの影響はわずかです。
System.nanoTime()
このメソッドは、最も正確なシステム・タイマーを使用して、単調なタイマー値を返します。戻り値はナノ秒単位ですが、タイマーの実際の時間単位はオペレーティング・システムとハードウェアによって異なる可能性があります。タイマー値を関連させるための通常のゼロ点はありません。したがって、有意なデータを得るには、少なくとも2回、時間を測定する必要があります。
nanoTime()
では、オペレーティング・システムごとに異なるメソッドを使用します。
Windows: QueryPerformanceCounter()
Solaris: gethrtime()
Linux: 使用できる場合はlibrt
のclock_gettime()
、それ以外の場合はgettimeofday()
タイマーの時間単位(および、Linuxでは、時間値の取得に使用されるメソッド)に関する情報を取得するには、-Xverbose:timing
コマンドライン・オプションを指定してJRockit JVMを起動します。
Windowsでの冗長タイミング・レポートの例を次に示します。
[INFO ][timing ] Fast time frequency is 1995000000hz [INFO ][timing ] Drift is 0.00000021 = per day 0.018secs (max 300.000) [INFO ][timing ] Hardware fast time enabled [INFO ][timing ] Counter timer using resolution of 1995MHz
System.currentTimeMillis()
このメソッドは、現在の時刻をミリ秒単位で返します。現在の時刻は1970年1月00:00:00 UTCからの時間として定義されます。
アプリケーション起動時のミリ秒とナノ時間
JVMの起動時にSystem.currentTimeMillis()
およびSystem.nanoTime()
の値を取得するには、-Xverbose:starttime
コマンドライン・オプションを使用します。
-Xverbose:starttime
コマンドライン・オプションの出力の例を次に示します。
INFO ][startti] VM start time: 1260962573921 millis 6922526 nanos 18442244770397334 ticks
millis
値はSystem.currentTimeMillis()
メソッドが提供する値と同じ値、nanos
値はSystem.nanoTime()
メソッドが提供する値です。
起動を高速化するチューニング
コマンドライン・オプションを使用してJVMをチューニングする方法に問題がある場合もあります。
起動を速くするためのJVMのチューニングに関するヒントは、『Oracle JRockitパフォーマンス・チューニング・ガイド』を参照してください。
最適化の問題の除外
まれに、最適化が原因でJVMの起動が遅くなることが、特にシングルCPUマシンの場合にあります。詳細は、5.2項「最適化の問題のトラブルシューティング」を参照してください。
アプリケーションの問題の除外
Javaアプリケーションの問題が原因で起動が遅いと判断した場合は、その問題の原因をアプリケーションの観点から調査します。多くは、不必要な同期や不十分な同期リソース数の影響を受けているメソッドに問題があると考えられます。ボトルネックの原因となっているメソッドを特定し、可能であればJavaアプリケーションのコードを変更します。
同期の問題の分析にはフライト・レコーダ・ツールを使用できます。詳細は、『Oracle JRockitフライト・レコーダ・ラン・タイム・ガイド』を参照してください。
Oracleサポートへの連絡
『Oracle JRockitパフォーマンス・チューニング・ガイド』に示されているチューニング解決策を試しても問題が解決できない場合は、第9章「サポートに関するオラクルへの連絡」の説明に従ってOracleサポートにご連絡ください。