java是一个异步的Throwable类的printStackTrace()
我测试了一些代码来读取类路径中可用的文件,但最终得到了一些关于Throwable类的printStackTrace()方法的有趣的东西
代码如下:
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.net.URL;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
public class Main {
public static void main(String[] args) throws IOException, URISyntaxException {
try {
System.out.println("before-test1");
test1(); // will throw exception
System.out.println("after-test1");
} catch (Exception e) {
System.out.println("entering catch-1");
e.printStackTrace();
System.out.println("exiting catch-1");
}
try {
System.out.println("before-test2");
test2();
System.out.println("after-test2");
} catch (Exception e) {
e.printStackTrace();
}
try {
System.out.println("before-test3");
test3();
System.out.println("after-test3");
} catch (Exception e) {
e.printStackTrace();
}
}
private static void test1() throws IOException {
String path = "classpath:/test.txt";
File file = new File(path);
String content = FileUtils.readFileToString(file, "UTF-8");
System.out.println("content = " + content);
}
private static void test2() throws IOException {
String path = "/test.txt";
InputStream in = Main.class.getResourceAsStream(path);
String content = IOUtils.toString(in);
System.out.println("content = " + content);
}
private static void test3() throws IOException, URISyntaxException {
String path = "/test.txt";
URL url = Main.class.getResource(path);
File file = new File(url.toURI());
String content = FileUtils.readFileToString(file, "UTF-8");
System.out.println("content = " + content);
}
}
测试的内容。txt仅为一行,如下所示:
anil bharadia
现在,该程序的预期输出如下所示:
before-test1
entering catch-1
java.io.FileNotFoundException: classpath:\test.txt (The filename, directory name, or volume label syntax is incorrect)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(Unknown Source)
at org.apache.commons.io.FileUtils.readFileToString(FileUtils.java:874)
at Main.test1(Main.java:50)
at Main.main(Main.java:16)
exiting catch-1
before-test2
content = anil bharadia
after-test2
before-test3
content = anil bharadia
after-test3
当我第一次运行这个类时,我得到了与上面相同的输出
然后在我再次运行同一个类之后,我得到了以下输出:
before-test1
entering catch-1
exiting catch-1
before-test2
content = anil bharadia
after-test2
before-test3
java.io.FileNotFoundException: classpath:\test.txt (The filename, directory name, or volume label syntax is incorrect)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(Unknown Source)
at org.apache.commons.io.FileUtils.readFileToString(FileUtils.java:874)
at Main.test1(Main.java:50)
at Main.main(Main.java:16)
content = anil bharadia
after-test3
在上面的输出中,堆栈跟踪是在调用它的catch块执行之后以及test2()的执行结束之后打印的
所以我认为printStackTrace()方法在某种程度上是异步的
我试图查找printStackTrace()的源代码,但发现以下代码对我没有帮助:
public void printStackTrace(PrintStream s) {
synchronized (s) {
s.println(this);
StackTraceElement[] trace = getOurStackTrace();
for (int i=0; i < trace.length; i++)
s.println("\tat " + trace[i]);
Throwable ourCause = getCause();
if (ourCause != null)
ourCause.printStackTraceAsCause(s, trace);
}
}
我试着用谷歌搜索,但没有找到任何解释
当我一次又一次尝试运行同一个类时,在许多情况下,我还发现了以下输出:
java.io.FileNotFoundException: classpath:\test.txt (The filename, directory name, or volume label syntax is incorrect)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(Unknown Source)
at org.apache.commons.io.FileUtils.readFileToString(FileUtils.java:874)
at Main.test1(Main.java:50)
at Main.main(Main.java:16)
before-test1
entering catch-1
exiting catch-1
before-test2
content = anil bharadia
after-test2
before-test3
content = anil bharadia
after-test3
这让我思考得更多,比如调用test1()方法之前堆栈跟踪是如何打印的。这是不可能的
# 1 楼答案
System.out.println("after-test3");
将输入写入out
流,并且printStackTrace()
方法将输入写入System.err
流# 2 楼答案
stacktrace打印到另一个流——它们被打印到错误流,而不是标准输出流。这就是为什么有时它们会以不同的顺序显示
# 3 楼答案
错误转到
System.err
流。 正常输出进入System.out
流这些流是由不同的线程编写的,所以如果再次运行,也可以预期输出中的序列不同
要获得所需的输出,您需要更改为:
这将把输出重定向到系统。外流