如果您的问题是由不可修复的Windows ProcessBuilder exit code 259 bug 引起的,那么有可用的解决方法:您需要做的就是确保您的子进程不会以状态码 259 退出并且 Windows JRE 不会报告java.lang.IllegalThreadStateException。
您可以通过使用Runtime.getRuntime().exec(cmd) 或ProcessBuilder(cmd) 执行以下命令轻松重现此问题:
String[] cmd = {"cmd.exe /c exit /b 259"};
如果您已经为子流程编写了代码,那么只需编辑您的代码,以便退出代码永远不会设置为 259。
如果您还没有为子进程编写代码,那么一个相当棘手的解决方法是使用“CMD.EXE”和将非零子进程退出适应退出代码的迷你脚本包装您的 Java 子进程启动0 或 1:
String[] fixed = new String[] { "cmd.exe", "/c",
"(call "+String.join(" ", cmd)+ ") || (echo !!! DETECTED ERROR!!! && exit 1)" };
笔记: 我不是 CMD 方面的专家。上面的修复绝对行不通对于某些命令或标点符号(例如,带有引号/空格等的命令),并且因为它在 CMD.EXE 环境设置下运行,结果可能与从调用 JVM 直接启动不同。
这是您可以测试的示例类:
/** Examples to test with and without the fix:
java Status259 "cmd.exe /c exit /b 0"
java Status259 "cmd.exe /c exit /b 25"
java Status259 "cmd.exe /c exit /b 259"
java Status259 %JAVA_HOME%\bin\java -cp your.jar Status259$StatusXXX 0
java Status259 %JAVA_HOME%\bin\java -cp your.jar Status259$StatusXXX 33
java Status259 %JAVA_HOME%\bin\java -cp your.jar Status259$StatusXXX 259
*/
public class Status259 {
public static class StatusXXX {
public static void main(String ... args) {
int status = args.length > 0 ? Integer.parseInt(args[0]) : 0;
System.out.println("StatusXXX exit code: "+status);
System.exit(status);
}
}
public static int exec(String[] cmd) throws IOException, InterruptedException {
System.out.println("exec "+Arrays.toString(Objects.requireNonNull(cmd)));
ProcessBuilder pb = new ProcessBuilder(cmd);
// No STDERR => merge to STDOUT - or call redirectError(File)
pb.redirectErrorStream(true);
Process p = pb.start();
// send sub-process STDOUT to the Java stdout stream
try(var stdo = p.getInputStream()) {
stdo.transferTo(System.out);
}
int rc = p.waitFor();
System.out.println("exec() END pid="+p.pid()+" CODE "+rc +' '+(rc == 0 ? "OK":"**** ERROR ****"));
return rc;
}
public static void main(String ... args) throws IOException, InterruptedException {
// COMMENT OUT NEXT LINE TO SEE EFFECT OF DIRECT LAUNCH:
args = fixStatus259(args);
int rc = exec(args);
System.exit(rc);
}
private static String[] fixStatus259(String[] cmd) {
System.out.println("fixStatus259 "+Arrays.toString(cmd));
return new String[] {
"cmd.exe", "/c",
"(call "+String.join(" ", cmd)+ ") || (echo !!! DETECTED ERROR!!! && exit 1)"
};
}
}