始める前に、『演習 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]); }
これはやや複雑なプローブの例です。あるメソッドがプログラム中に存在し、これは即時に実行されますが、長い時間かかる (例えば 100ms を超える) ことがあるとします。
メソッドが実行されるたびにエントリーおよび終了の時間をメモするようなプローブを記述することができます。実行時間が短いときは、プローブは何もしません。実行時間が長いと、プローブはメソッドへの引き数と、その時のプログラム状態に関するその他の重要な情報を報告します。これによって、環境が実行時間の長期化につながるかどうかを判断できます。
プローブを記述するとき、以下の点に注意してください。
Probekit の「クラス有効範囲でのフラグメント」機能を使用すれば、任意のメソッドの外部にある生成済みクラスにコンパイルされる Java コード・フラグメントを記述できます。フラグメントはこの場合、エントリー・フラグメントおよび終了フラグメントの両方によって使用される entryTime と呼ばれる静的フィールドの定義に使用されます。
このエレメントをプローブに追加するには、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 を使用してレポートを出力します。
上記のプローブは、再帰的 (直接的または間接的) なメソッドでは機能せず、また複数のスレッドで同時に実行されるメソッドでも機能しません。再帰的な問題を解決するには、エントリー時間をスタックに記録します。マルチスレッドの問題を解決するには、スタックを 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: 複雑なプローブ・ロジックへのランタイム・ライブラリーの使用』へ進んでください。