この演習を開始する前に、『演習 1.3: プローブの適用』を完了する必要があります。
Probekit を使用すると、実際に起こる多くのデバッグ問題やランタイム分析問題を解決できます。 これまでの演習で、プローブの作成とデプロイに関する基本事項を既に学習したので、この演習と次の 演習では、これらの作業の手順を説明する代わりに、読者自身のアプリケーションを調査するために作成する プローブに関する参考情報を提供します。
ここでは、サーブレット内のあるメソッドが時々例外をスローすると想定します。 なお、出力されるログ・メッセージは、問題の内容を明確に示していないためあまり役に立たないとします。 詳細な情報を得るためには、このメソッドが例外をスローするたびに実行されるプローブを作成できます。 このプローブのフラグメント内の Java コードは、例外メッセージと共にメソッドの引数をログに記録で きます。 これにより、例外がスローされる理由を調べやすくなります。
このプローブを作成してデプロイする際には、以下のことに注意してください。
System.out.println("[Exception probe triggered!]"); for (int i = 0; i < args.length; i++) { System.out.println("Argument " + i + "=" + args[i]); }
ここでは、かなり複雑なプローブの例を紹介します。 例えば、プログラム内のあるメソッドが、通常は短時間で実行されるのに、時によっては長い時間 (例 えば 100 ミリ秒を超える時間) をかけて実行されるとします。
このような場合は、このメソッドが実行されるたびに開始時と終了時を確認するプローブを作成できます。 実行時間が短い場合は、プローブは何もしません。 実行時間が長い場合は、プローブは、そのメソッドの引数と、その時点のプログラム状態に関する他の 重要情報を報告します。 これにより、長い実行時間の原因となっている状況を特定できます。
このプローブを作成する際には、以下のことに注意してください。
Probekit の「クラス有効範囲でのフラグメント」機能を使用して、すべてのメソッドの外側の生成済み クラスにコンパイルされる Java コード・フラグメントを作成できます。 この場合は、このフラグメントを使用して、entry フラグメントと exit フラグメントの両 方で使用される entryTime という名前の static フィールドを定義します。
このエレメントをプローブに追加するには、Probekit エディターで「Probe」エレメントをク リックします。これにより、エディターでは、クラス有効範囲でのフラグメントの Java コードを入力 するためのフィールドが表示されます。
static long entryTime; static final long thresholdDuration = 100;
entryTime = System.currentTimeMillis();
long now = System.currentTimeMillis(); if ((now - entryTime) > thresholdDuration) { System.out.println( "[Spent a long time in " + className + "." + methodName + ": this=" + thisObject + "]"); }
メソッド入り口で、このプローブは現在時刻を記録します。 メソッド出口で、このプローブは、メソッド入り口で記録された時刻と現在時刻を比較し、これらの時刻の 差が「thresholdDuration」で指定した時間を超えている場合は、System.out を使用してレポートを出力します。
前のセクションで説明したプローブは、再帰的 (直接または間接) なメソッドに対しては有効ではなく 、マルチスレッドで同時に実行される可能性のあるメソッドに対しても有効ではありません。 再帰に関する問題は、メソッド入り口の時刻をスタック (Stack) に記録することで解決できます 。マルチスレッドに関する問題は、このスタックを ThreadLocal 変数に保管することで解決できます。
再帰呼び出しに対応したスレッド・セーフなプローブを作成するためには、以下が必要です。
static ThreadLocal tl = new ThreadLocal() { public Object initialValue() { return new Stack(); } }; static long thresholdDuration = 100; // Report if time is over 100ms
long now = System.currentTimeMillis(); Stack stk = (Stack)tl.get(); stk.push(new Long(now));
long now = System.currentTimeMillis(); Stack stk = (Stack)tl.get(); long entryTime = ((Long)stk.pop()).longValue(); if (now - entryTime > thresholdDuration) { System.out.println( "[Spent a long time in " + cName + "." + mName + ": this=" + thisObj + "]"); }
『演習 1.5: 複雑なプローブ・ロジックのためのランタイム・ライブ ラリーの使用』に進んで、チュートリアルを続けてください。