为什么异常方法的 printstacktrace() 在调用时不打印到控制台?
Why is printstacktrace() of exception method does not print to console when ever called?
每当我们尝试使用 printStackTrace()
方法打印堆栈跟踪时,为什么输出不符合预期顺序?假设我们有一些打印语句和 printStackTrace()
并且输出不是预期的顺序。
public class Main {
public static void main(String[] args) {
Main m = new Main();
m.test1();
System.out.println("main method");
}
public void test1() {
System.out.println(test2());
System.out.println("test1");
}
public int test2() {
try {
throw new Exception();
} catch (Exception e) {
System.out.println("exception");
e.printStackTrace();
} finally {
}
return 2;
}
}
预期输出应为:
exception
java.lang.Exception
at com.infor.jdbc.Main.test2(Main.java:18)
at com.infor.jdbc.Main.test1(Main.java:12)
at com.infor.jdbc.Main.main(Main.java:7)
2
test1
main method
但实际结果是:
exception
java.lang.Exception //from printStackTrace
2
test1
main method
at com.infor.jdbc.Main.test2(Main.java:18) //from printStackTrace
at com.infor.jdbc.Main.test1(Main.java:12)
at com.infor.jdbc.Main.main(Main.java:7)
来自 Javadoc:
void printStackTrace()
Prints this throwable and its backtrace to the standard error stream.
注意它说 标准错误流。您的 System.out.println(...)
语句写入 标准输出 ,这是一个不同的流。它们在控制台上的交错显示方式取决于操作系统以及流的缓冲方式。任一输出都是 "correct".
printstacktrace()
方法(默认情况下)输出到错误流。
默认情况下,错误流与控制台相同(std out 默认也是控制台)。
由于您没有锁定机制(OS 不关心它们是否交错),printstacktrace 和 stdout 的输出交错。
尝试 e.printstacktrace(System.out)
...,您将按预期顺序看到它们。
缓冲输出流被写入两个单独的输出而不刷新("stderr" 和 "stdout")。打印您的消息,打印堆栈跟踪,然后刷新,您将看到您预期的行为。
public int test2() {
try {
throw new Exception();
} catch (Exception e) {
System.err.println("exception");
e.printStackTrace(System.err);
System.err.flush();
} finally {
}
return 2;
}
如果您查看不带参数的 printStackTrace
重载,您会发现它调用带 PrintStream
参数的重载,其中 System.err
:
public void printStackTrace() {
printStackTrace(System.err);
}
/**
* Prints this throwable and its backtrace to the specified print stream.
*
* @param s {@code PrintStream} to use for output
*/
public void printStackTrace(PrintStream s) {
printStackTrace(new WrappedPrintStream(s));
}
这也是documented。
另一方面,您正在标准输出流上打印输出,System.out
。这是两个不同的流,它们都会打印到控制台 "in parallel"。有时一个接管,有时另一个接管,因此您看到的输出。
如果您调用 printStackTrace(System.out)
,您将看到预期的输出。
每当我们尝试使用 printStackTrace()
方法打印堆栈跟踪时,为什么输出不符合预期顺序?假设我们有一些打印语句和 printStackTrace()
并且输出不是预期的顺序。
public class Main {
public static void main(String[] args) {
Main m = new Main();
m.test1();
System.out.println("main method");
}
public void test1() {
System.out.println(test2());
System.out.println("test1");
}
public int test2() {
try {
throw new Exception();
} catch (Exception e) {
System.out.println("exception");
e.printStackTrace();
} finally {
}
return 2;
}
}
预期输出应为:
exception
java.lang.Exception
at com.infor.jdbc.Main.test2(Main.java:18)
at com.infor.jdbc.Main.test1(Main.java:12)
at com.infor.jdbc.Main.main(Main.java:7)
2
test1
main method
但实际结果是:
exception
java.lang.Exception //from printStackTrace
2
test1
main method
at com.infor.jdbc.Main.test2(Main.java:18) //from printStackTrace
at com.infor.jdbc.Main.test1(Main.java:12)
at com.infor.jdbc.Main.main(Main.java:7)
来自 Javadoc:
void printStackTrace()
Prints this throwable and its backtrace to the standard error stream.
注意它说 标准错误流。您的 System.out.println(...)
语句写入 标准输出 ,这是一个不同的流。它们在控制台上的交错显示方式取决于操作系统以及流的缓冲方式。任一输出都是 "correct".
printstacktrace()
方法(默认情况下)输出到错误流。
默认情况下,错误流与控制台相同(std out 默认也是控制台)。
由于您没有锁定机制(OS 不关心它们是否交错),printstacktrace 和 stdout 的输出交错。
尝试 e.printstacktrace(System.out)
...,您将按预期顺序看到它们。
缓冲输出流被写入两个单独的输出而不刷新("stderr" 和 "stdout")。打印您的消息,打印堆栈跟踪,然后刷新,您将看到您预期的行为。
public int test2() {
try {
throw new Exception();
} catch (Exception e) {
System.err.println("exception");
e.printStackTrace(System.err);
System.err.flush();
} finally {
}
return 2;
}
如果您查看不带参数的 printStackTrace
重载,您会发现它调用带 PrintStream
参数的重载,其中 System.err
:
public void printStackTrace() {
printStackTrace(System.err);
}
/**
* Prints this throwable and its backtrace to the specified print stream.
*
* @param s {@code PrintStream} to use for output
*/
public void printStackTrace(PrintStream s) {
printStackTrace(new WrappedPrintStream(s));
}
这也是documented。
另一方面,您正在标准输出流上打印输出,System.out
。这是两个不同的流,它们都会打印到控制台 "in parallel"。有时一个接管,有时另一个接管,因此您看到的输出。
如果您调用 printStackTrace(System.out)
,您将看到预期的输出。