1

System.err削除したい誤ったスタック トレースが出力されているのを見ていますが、呼び出している行を特定するのに苦労していprintStackTrace()ます。どの回線がその呼び出しを行っているかを把握する賢い方法はありますか?

特に、呼び出しが自分のコードで行われているのか、ライブラリで行われているのか、まだわかりません。検索する場所 (自分のコードか他の人のコードか) を絞り込むだけでも役に立ちます。

編集:明確にするために、スタックトレースが出力されているをprintStackTrace()スローした行ではなく、呼び出している行を探しています。Exception(前者への答えは... まあ... スタック トレースです。:) スタック トレースを調べ、すべてのprintStackTrace()ステップで可能性のある呼び出しを探すことで、明らかな場所をすべて調べましたが、何も見つかりませんでした。[a] 呼び出しがあり、私がばかである (確かに可能性があります) か、[b]Exceptionが渡されて他の場所に印刷されているかのいずれかです。printStackTrace()これが、電話を見つけるのに非常に苦労している理由です。printStackTrace()呼び出しはthrowException.

編集:出力を監視することSystem.errは素晴らしい提案であり、うまく機能します。これが私が試したものです:

final PrintStream systemErr=System.err;
System.setErr(new PrintStream(new OutputStream() {
    @Override
    public void flush() throws IOException {
        systemErr.flush();
    }

    @Override
    public void close() throws IOException {
        systemErr.close();
    }

    @Override
    public void write(byte[] buf, int off, int len) throws IOException {
        String s=new String(buf, Charset.defaultCharset());
        if(s.contains("Socket closed"))
            new Exception().printStackTrace();
        systemErr.write(buf, off, len);
    }

    @Override
    public void write(int b) throws IOException {
        systemErr.write(b);
    }
}));

ここで、私が監視していたメッセージ"Socket closed"は、Exceptionメッセージに表示された でした。write(byte[],int,int)(a) 基礎となるコードが最終的に を介してではなくを呼び出していたことwrite(int)、および (b) チャンクが、監視していたメッセージを異なる呼び出し間で分割しなかったことは、少し幸運でした。しかし、そうは言っても、これは魅力的でした。助けてくれてありがとう、みんな!

4

4 に答える 4

2

たとえば、元の値をラップするなど、System.err と System.out に新しい値を指定できます。

次に、新しい値で \n をテストし、そこにブレーク ポイントを設定するか、プログラムでコール スタックを調べることができます。

これを行っている間は、通常のロギングを無効にしたいでしょう。

于 2013-06-08T22:00:41.683 に答える
1

再現できる場合System.setErr()は、プログラムの最初に を呼び出すだけで、ストリームで行われたすべての呼び出しをログに記録するカスタム ストリームをスタック トレースと共に渡すことができますSystem.err。スマートで、誤ったスタック トレースの一部である特定のキーワードが出力された場合にのみ呼び出しをログに記録することもできます。

于 2013-06-08T22:00:43.357 に答える
0

これは、誤ったストリーム出力をデバッグするための汎用クラスです。大部分は sigpwned のコードと Thorbjorn のアイデアからコピーしただけですが、フレンドリーな API を使用しています。また、トレースは各行にプレフィックス付きで出力されるため、例外を作成した呼び出しのスタック トレースと、例外のスタック トレースを出力している行のスタック トレースを区別できます。

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.charset.Charset;

/** Utility methods for figuring out when a given string is being printed to System.out or System.err. */
public class StreamDebug {
    /** Stores the pristine System.err stream before it is clobbered by other methods. */
    private static final PrintStream PRISTINE_SYS_ERR = System.err;

    /** Dumps a stack trace if the trigger string is printed to System.out. */
    public static void dumpIfSysOutContains(String trigger) {
        System.setOut(wrapAndDumpIfContains(System.out, trigger));
    }

    /** Dumps a stack trace if the trigger string is printed to System.err. */
    public static void dumpIfSysErrContains(String trigger) {
        System.setErr(wrapAndDumpIfContains(System.err, trigger));
    }

    /**
     * When dumping the stack trace, all lines in the trace before this delimiter will be ignored.
     * This is chosen to match the "new Throwable().printStackTrace(new PrintWriter(sw));" line below.
     */
    private static final String INTERESTING_DELIMITER = "java.lang.Throwable.printStackTrace";

    /** 
     * Returns a PrintStream which will redirect all of its output to the source PrintStream.  If
     * the trigger string is passed through the wrapped PrintStream, then it will dump the
     * stack trace of the call that printed the trigger. 
     * 
     * @param source    the returned PrintStream will delegate to this stream
     * @param trigger   the string which triggers a stack dump
     * @return          a PrintStream with the above properties
     */
    public static PrintStream wrapAndDumpIfContains(final PrintStream source, final String trigger) {
        return new PrintStream(new OutputStream() {
            @Override
            public void flush() throws IOException {
                source.flush();
            }

            @Override
            public void close() throws IOException {
                source.close();
            }

            @Override
            public void write(byte[] buf, int off, int len) throws IOException {
                String s = new String(buf, off, len, Charset.defaultCharset());
                if (s.contains(trigger)) {
                    // print the triggered header
                    PRISTINE_SYS_ERR.println("+----------\\");
                    PRISTINE_SYS_ERR.println("| TRIGGERED \\");

                    // put the stack trace into an array of strings
                    StringWriter sw = new StringWriter();
                    new Throwable().printStackTrace(new PrintWriter(sw));
                    String[] lines = sw.toString().replaceAll("\\r\\n", "\n").split("\\n"); // stack trace as a string

                    // print each line of the stacktrace with a prefix to differentiate from the "standard" stream
                    // but don't print until we've gotten past the INTERESTING_DELIMITER
                    boolean foundInterestingDelimiter = false;
                    boolean pastInterestingDelimiter = false;
                    for (String line : lines) {
                        // set foundInterestingDelimiter to true when we find the delimiter
                        if (!foundInterestingDelimiter && line.contains(INTERESTING_DELIMITER)) {
                            foundInterestingDelimiter = true;
                        }
                        // set pastInterestingDelimiter to true when the line no longer contains the delimiter
                        if (foundInterestingDelimiter && !pastInterestingDelimiter && !line.contains(INTERESTING_DELIMITER)) {
                            pastInterestingDelimiter = true;
                        }
                        // only print the stack trace once we've gotten past the interesting delimiter
                        if (pastInterestingDelimiter) {
                            PRISTINE_SYS_ERR.print("| ");
                            PRISTINE_SYS_ERR.println(line.trim());
                        }
                    }

                    // print the triggered footer
                    PRISTINE_SYS_ERR.println("| TRIGGERED /");
                    PRISTINE_SYS_ERR.println("+----------/");
                }
                source.write(buf, off, len);
            }

            @Override
            public void write(int b) throws IOException {
                source.write(b);
            }
        });
    }
}
于 2014-01-25T02:20:38.257 に答える
0

最初のスタックは、try で囲まれた行を出力し、関連するキャッチを探します。出力はここにあります。

キャッチされた例外が、出力される通常の引数として別のメソッドに渡される場合、それもここにあります。Eclipse などの最新の IDE では、コードや型に従うことができます。

あなたの問題に関するより多くのコードは、私たちがあなたを助けようとするのに役立ちます...

于 2013-06-08T21:57:03.033 に答える