【问题标题】:process.waitFor() throws IllegalThreadStateExceptionprocess.waitFor() 抛出 IllegalThreadStateException
【发布时间】:2022-10-05 23:16:36
【问题描述】:

环境

Windows 10
Java 1.8

过程

I am running a 7zip\'s zip task.
The process takes 2 to 3 hours to complete.

例外

java.lang.IllegalThreadStateException:进程尚未退出
在 java.lang.ProcessImpl.exitValue(ProcessImpl.java:443)
在 java.lang.ProcessImpl.waitFor(ProcessImpl.java:452at

我的代码

int exitValue = -1;
Process start = null;
try
{
        ProcessBuilder processBuilder = new ProcessBuilder(commands);
        start = processBuilder.start();
        try(BufferedReader ipBuf = new BufferedReader(new InputStreamReader(start.getInputStream())))
        {
            String line = null;
            while ((line = ipBuf.readLine()) != null)
            {
                LOGGER.info(line);
            }
        }
        try(BufferedReader errBuf = new BufferedReader(new InputStreamReader(start.getErrorStream())))
        {
            String line;
            while ((line = errBuf.readLine()) != null)
            {
                LOGGER.warning(line);
            }
        }
        start.waitFor();
        exitValue = start.exitValue();
}
finally
{
        if (start != null)
        {
            start.destroy();
        }
}
return exitValue;

我无法找到此问题的根本原因。

笔记:我已经在同一个类似的演示实例上尝试过这个过程 机器,它工作正常。

请帮我解决这个问题,谢谢。

  • @Holger ...这是由GetExitCodeProcess 的一个惊人的脑死亡Windows 实现引起的,如果它不是悲剧的话会很有趣。 Java 无法解决这个问题。
  • 我也在 Linux 中看到了这个问题

标签: java java-process-runtime


【解决方案1】:

如果您的问题是由不可修复的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)"
        };
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-07
    • 1970-01-01
    • 1970-01-01
    • 2010-10-15
    • 2011-01-10
    相关资源
    最近更新 更多