Java StackOverflowError 在 java.io.PrintStream.write(PrintStream.java:480) 并且没有进一步的堆栈跟踪
Java StackOverflowError at java.io.PrintStream.write(PrintStream.java:480) and no further stack trace
我正在 运行ning 一个由另一个人编写的 Java 程序,其数据量超过了该程序最初设计的数据量,例如输入文件长 10 倍,大致为 运行 的二次方。我遇到了不同的问题,现在的目标是一点一点地解决它们。
在执行期间,当大量输出已被打印(重定向到文件)时,我得到以下 输出:
Exception in thread "main" java.lang.WhosebugError
at java.io.PrintStream.write(PrintStream.java:480)
[...]
at java.io.PrintStream.write(PrintStream.java:480)
堆栈跟踪是让我感到困惑的第一件事,因为它是一次又一次地重复同一行。此外,它没有给出问题发生在代码或执行中的位置。
我的想法/研究
- 堆栈溢出错误
- 可能是内存太少了。使用 -Xmx110G 标志,我提供了 110 G 内存并在执行时对其进行监控,仅使用了大约 32 G。所以这可能不是这里的问题。
- 可能是因为编程错误导致死循环而抛出。但是,我真的无法检查这个,因为我对代码不够熟悉,堆栈跟踪也不能帮助我找到代码中问题的位置。
- [hypothesis]可能是造成的,因为输出的写入比执行和新的print/write调用慢。不过,为什么没有进一步的堆栈跟踪?我该如何检查并解决这个问题?
打印流
只有搜索后的代码片段"PrintStream"
// reset output stream to suppress the annoying output of the Apache batik library. Gets reset after lib call.
OutputStream tmp=System.out;
System.setOut(new PrintStream(new org.apache.commons.io.output.NullOutputStream()));
drawRes.g2d.stream(new FileWriter(svgFilePath), false);
System.setOut(new PrintStream(tmp));
- [假设] 写入 void / null 不起作用
- [workaround] 如果跳过输出流的更改并且只是 "live" 与创建的大输出程序似乎 运行 (进入其他问题,但这是另一种情况)。知道为什么会这样吗?
求教
如果您对发生的事情有任何建议,Java 代码具体做什么,请帮助我理解它。尤其是堆栈跟踪让我很沮丧,因为它没有提供开始修复的地方。我也很感谢关于如何解决这个问题、获取堆栈跟踪、修复代码以避免 Whosebug 等的一般方法。
一些系统环境事实
- Linux机器
- 128G内存
Java
openjdk version "1.8.0_121"
OpenJDK Runtime Environment (IcedTea 3.3.0) (suse-28.1-x86_64)
OpenJDK 64-Bit Server VM (build 25.121-b13, mixed mode)
请询问您是否需要更多信息!
备注
- 我对Java比较陌生,所以非常感谢大家的建议(程序不是我写的)
- 这是我第一次 post 在 Whosebug 上,请告诉我在哪里可以改进我的提问和格式
- 我的母语不是英语,所以请原谅我的错误,并随时寻求理解或纠正我
感谢大家的回复!
这两行看起来很可疑:
OutputStream tmp=System.out;
//...
System.setOut(new PrintStream(tmp));
System.out
已经是 PrintStream
,所以恕我直言,这些行应该是
PrintStream tmp=System.out;
//...
System.setOut(tmp);
否则会发生 PrintStream
s 内的 PrintStream
s 几乎无休止的包装。 PrintStreams 的嵌套仅限于 Java 堆 space - 但调用级别嵌套要低得多。
为了验证我的假设,我创建了一个小测试程序,首先包装 System.out
20 次并打印堆栈跟踪以验证调用链。之后它包装 System.out
10_000 次并产生 WhosebugException。
import java.io.OutputStream;
import java.io.PrintStream;
public class CheckPrintStream {
public static void main(String[] args) {
PrintStream originalSystemOut = System.out;
System.setOut(new PrintStream(System.out) {
@Override
public void write(byte buf[], int off, int len) {
originalSystemOut.write(buf, off, len);
if (len > 2) {
new RuntimeException("Testing PrintStream nesting").printStackTrace(originalSystemOut);
}
}
});
for (int i = 0; i < 20; i++) {
wrapSystemOut();
}
System.out.println("Hello World!");
for (int i = 20; i < 10_000; i++) {
wrapSystemOut();
}
System.out.println("crash!");
}
private static void wrapSystemOut() {
OutputStream tmp = System.out;
System.setOut(new PrintStream(System.out));
}
}
大约 6000 到 7000 个 PrintWriters 的嵌套足以产生堆栈溢出。
我正在 运行ning 一个由另一个人编写的 Java 程序,其数据量超过了该程序最初设计的数据量,例如输入文件长 10 倍,大致为 运行 的二次方。我遇到了不同的问题,现在的目标是一点一点地解决它们。
在执行期间,当大量输出已被打印(重定向到文件)时,我得到以下 输出:
Exception in thread "main" java.lang.WhosebugError
at java.io.PrintStream.write(PrintStream.java:480)
[...]
at java.io.PrintStream.write(PrintStream.java:480)
堆栈跟踪是让我感到困惑的第一件事,因为它是一次又一次地重复同一行。此外,它没有给出问题发生在代码或执行中的位置。
我的想法/研究
- 堆栈溢出错误
- 可能是内存太少了。使用 -Xmx110G 标志,我提供了 110 G 内存并在执行时对其进行监控,仅使用了大约 32 G。所以这可能不是这里的问题。
- 可能是因为编程错误导致死循环而抛出。但是,我真的无法检查这个,因为我对代码不够熟悉,堆栈跟踪也不能帮助我找到代码中问题的位置。
- [hypothesis]可能是造成的,因为输出的写入比执行和新的print/write调用慢。不过,为什么没有进一步的堆栈跟踪?我该如何检查并解决这个问题?
打印流
只有搜索后的代码片段"PrintStream"
// reset output stream to suppress the annoying output of the Apache batik library. Gets reset after lib call. OutputStream tmp=System.out; System.setOut(new PrintStream(new org.apache.commons.io.output.NullOutputStream())); drawRes.g2d.stream(new FileWriter(svgFilePath), false); System.setOut(new PrintStream(tmp));
- [假设] 写入 void / null 不起作用
- [workaround] 如果跳过输出流的更改并且只是 "live" 与创建的大输出程序似乎 运行 (进入其他问题,但这是另一种情况)。知道为什么会这样吗?
求教
如果您对发生的事情有任何建议,Java 代码具体做什么,请帮助我理解它。尤其是堆栈跟踪让我很沮丧,因为它没有提供开始修复的地方。我也很感谢关于如何解决这个问题、获取堆栈跟踪、修复代码以避免 Whosebug 等的一般方法。
一些系统环境事实
- Linux机器
- 128G内存
Java
openjdk version "1.8.0_121" OpenJDK Runtime Environment (IcedTea 3.3.0) (suse-28.1-x86_64) OpenJDK 64-Bit Server VM (build 25.121-b13, mixed mode)
请询问您是否需要更多信息!
备注
- 我对Java比较陌生,所以非常感谢大家的建议(程序不是我写的)
- 这是我第一次 post 在 Whosebug 上,请告诉我在哪里可以改进我的提问和格式
- 我的母语不是英语,所以请原谅我的错误,并随时寻求理解或纠正我
感谢大家的回复!
这两行看起来很可疑:
OutputStream tmp=System.out;
//...
System.setOut(new PrintStream(tmp));
System.out
已经是 PrintStream
,所以恕我直言,这些行应该是
PrintStream tmp=System.out;
//...
System.setOut(tmp);
否则会发生 PrintStream
s 内的 PrintStream
s 几乎无休止的包装。 PrintStreams 的嵌套仅限于 Java 堆 space - 但调用级别嵌套要低得多。
为了验证我的假设,我创建了一个小测试程序,首先包装 System.out
20 次并打印堆栈跟踪以验证调用链。之后它包装 System.out
10_000 次并产生 WhosebugException。
import java.io.OutputStream;
import java.io.PrintStream;
public class CheckPrintStream {
public static void main(String[] args) {
PrintStream originalSystemOut = System.out;
System.setOut(new PrintStream(System.out) {
@Override
public void write(byte buf[], int off, int len) {
originalSystemOut.write(buf, off, len);
if (len > 2) {
new RuntimeException("Testing PrintStream nesting").printStackTrace(originalSystemOut);
}
}
});
for (int i = 0; i < 20; i++) {
wrapSystemOut();
}
System.out.println("Hello World!");
for (int i = 20; i < 10_000; i++) {
wrapSystemOut();
}
System.out.println("crash!");
}
private static void wrapSystemOut() {
OutputStream tmp = System.out;
System.setOut(new PrintStream(System.out));
}
}
大约 6000 到 7000 个 PrintWriters 的嵌套足以产生堆栈溢出。