いらっしゃいませ。
某国産の食品の品質がいろいろといわれた昨今ですが、やはり、流通路というか出自というのは重要な情報ですよね。
なお、当店の素材はできるだけ本家の厳選された素材に基づくようにしております。
スタックトレースでの追跡
デバッグの際に非常に役立つスタックトレース。活用していますか?
これはスレッドの流れを示しています。いわば流通路のようなものです。
メソッドに不正な引数が渡された場合、この流通路を遡ればどこの誰がばったもんを流したのか調査することが出来ます。犯人を見つけたらとっちめてやりましょう。
しかし、キャッシュされるオブジェクトや、staticフィールドに保持されるオブジェクトなどスレッドの流れとは一旦隔絶される場合、トレースを追いかけても犯人をつかめないことがあります。
/** Object置き場。ここに置いたのを処理する */
private Object object;
/** 置き場にObjectを置く */
public void setObject(Object object) {
this.object = object;
}
/** 置き場のデータを処理するメソッド */
public void hoge() {
Object o = this.object;
// 置き場にあるデータを使って処理を進める
// ...
}
このコードではhoge()メソッドの呼び出しに直接手渡しでオブジェクトが渡されるわけではありません。そのため、何時どこで誰がObject置き場にデータを置いたのか、スタックトレースからは追いかけることができません。
オブジェクトの出自
このスタックトレース、プログラムで扱うことができるようになっています。 Thread#getStackTrace()で対象スレッドの現時点でのスタックトレースを取得することが出来ます。
オブジェクトの生成時にこれをとっておいたらどうでしょうか?
/** インスタンス生成時のスタックトレース */
private StackTraceElement[] createLog;
/** コンストラクタ */
public TraceTest() {
// カレントスレッドからスタックトレースを取得
this.createLog = Thread.currentThread().getStackTrace();
}
このように、オブジェクトにスタックトレースの保管フィールドを用意し、コンストラクタの時点でスタックトレースをとっておきます。
すると、デバッグ時にオブジェクトの作られた場所が分かるという寸法です。
いかがでしょうか。これでデバッグの効率が上がると思いませんか?
環境ごとの注意点
Thread#getStackTrace()はJavaSE5.0からのサポートです。
JDK1.4の場合はExceptionをnewして生成したExceptionからgetStackTrace()してやることで同様の効果を得られます。
StackTraceElementクラスがJDK1.4からのサポートなので、JDK1.3以前の場合はExceptionをnewして printStackTrace(PrintStream)を利用し、ByteArrayOutputStreamか何かに繋げた PrintStreamを作成してそこにトレースを書き出すという手法を使います。文字列情報になってしまいますが、デバッグには十分でしょう。
なお、C#でもほぼ同等のことができるようですね。具体的なやり方は…誰かが書いてくれることを期待しましょう。
投稿日時 : 2007年8月20日 12:04