5

スレッド ダンプには豊富な情報が含まれています。たとえば、いくつかのアクションが複数回起動された疑いがある場合、アクションが起動されるたびにスタック トレースをダンプし、誤ったアクションの起動についてスタックを調査するだけで済みます。

特定の状況では、開発者は順次実行の概念的な単純さを放棄することが推奨されます。たとえば、Swing は SwingWorker ヘルパーを提供して、シングルスレッド EDT の制限を回避します。ここで、スタック トレースをダンプしても、アクションは SwingWorker によって起動され、誰が SwingWorker タスクを開始したかに関する情報がないため、役に立ちません。

では、どのようにトラブルシューティングを行えばよいのでしょうか? スレッドダンプを「リダイレクト」して、真の原因を追跡する巧妙なトリックはありますか?

4

2 に答える 2

2

SwingWorkerを拡張して、スタックの作成時(または実行時)にスタックを記録できますが、最終的なものであるため、別の実行メソッドを作成する必要があります。原因の作成は比較的費用がかかるため、デバッグ時にのみ作成することをお勧めします(ログレベルなどを確認してください)

import java.util.concurrent.ExecutionException;
import javax.swing.SwingWorker;

public abstract class TracedSwingWorker<T, V> extends SwingWorker<T, V> {

    private final Exception cause;

    public TracedSwingWorker() {
        super();
        this.cause = new Exception("TracedSwingWorker created at:");
    }

    @Override
    protected final T doInBackground() throws Exception {
        try {
            return doWorkInBackground();
        }
        catch(Exception e) {
            if(this.cause != null) {
                Throwable cause = e;
                while(cause.getCause() != null) {
                    cause = cause.getCause();
                }

                cause.initCause(this.cause);
            }

            throw e;
        }
    }

    protected abstract T doWorkInBackground();

    // just for testing
    public static void main(String[] args) {
        new TracedSwingWorker<Void, Void>() {
            @Override
            protected Void doWorkInBackground() {
                throw new IllegalArgumentException("Exception in TracedSwingWorker!");
            }

            @Override
            protected void done() {
                try {
                    get();
                }
                catch (InterruptedException e) {
                    e.printStackTrace();
                }
                catch (ExecutionException e) {
                    e.printStackTrace();
                }
            }
        }.execute();
    }
}

プリント:

java.util.concurrent.ExecutionException: java.lang.IllegalArgumentException: Exception in SwingWorker!
        at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222)
<snip>
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
        at java.lang.Thread.run(Thread.java:662)
    Caused by: java.lang.Exception: SwingWorker created at:
        at TracedSwingWorker.<init>(TracedSwingWorker.java:15)
        at TracedSwingWorker$2.<init>(TracedSwingWorker.java:60)
        at TracedSwingWorker.main(TracedSwingWorker.java:60)
于 2012-08-02T11:16:18.957 に答える
0

すでに知っていることを言っているかもしれませんが、ThreadDumpをお勧めします

http://www.oracle.com/technetwork/java/javase/tooldescr-136044.html#gbmpn

IDE を使用している場合は、これで問題ありません。

NetBeans http://netbeans.org/kb/docs/java/debug-multithreaded.html

これにはEclipseをよく使用しました。デバッガー ビューには、複数のスレッドを視覚化および追跡し、スタックを出力して一時停止する手段があります。

于 2012-08-02T00:21:08.437 に答える