Java - Runtime.exec() 未能 运行

Java - Runtime.exec() fails to run

当我尝试 运行 任何 Runtime.exec() 命令时,就像这个简单的命令来打印 java 版本:

String [] cmd = { "java", "-version" };
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec(cmd);

BufferedReader stdError = new BufferedReader( new InputStreamReader( process.getErrorStream() ) );
String s = null;

while ( ( s = stdError.readLine() ) != null )
    System.out.println(s);

它工作得很好,但是如果我使用与我的 Java 应用程序捆绑在一起的 JRE,我总是会收到错误消息,提示 java 未知:

java.io.IOException: Cannot run program "java": error=2, No such file or directory
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)
    at java.lang.Runtime.exec(Runtime.java:620)
    at java.lang.Runtime.exec(Runtime.java:450)
    at java.lang.Runtime.exec(Runtime.java:347)
    at org.runner.Runner.main(Runner.java:11)

为什么在使用捆绑的 JRE 时会发生这种情况?

确保将 java 添加到 PATH 环境变量。如果不是,请使用可执行文件的绝对路径。例如:

String [] cmd = { "//usr//bin//java", "-version" };
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class PP {

    public void pop(){
    String [] cmd = { "java", "-version" };
    Runtime runtime = Runtime.getRuntime();
    Process process = null;
    try {
        process = runtime.exec(cmd);
    } catch (IOException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }

    BufferedReader stdError = new BufferedReader( new InputStreamReader( process.getErrorStream() ) );
    String s = null;

    try {
        while ( ( s = stdError.readLine() ) != null )
            System.out.println(s);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    }
        public static void main(String []args){
            PP pp=new PP();
        pp.pop();
        }

}

经过大量调查,我能够解决这个问题。我会在这里添加我的工作解决方案,可能会帮助遇到同样问题的人:

此问题是由报告的 JDK 错误引起的: https://bugs.java.com/view_bug.do?bug_id=5049299

因为我在 Mac OS X 上遇到这个问题,所以我可以安全地使用 "fork" 而不是 "posix_spawn" 通过设置 Java 系统 属性:

if( isMacOSX() ) System.setProperty( "jdk.lang.Process.launchMechanism", "FORK" );

这可能是一个令人沮丧的解决方案,但它确实解决了我在 Mac OS X 上的一个大问题。

我 运行 在 MacOS 上也遇到过这个问题。它仅在使用捆绑的 jre 时影响我的应用程序。切换到 'fork' 时(正如您在回答中所做的那样)对我有用。我很好奇必须有一个 'better' 解决方案,因为你指出的错误报告是几年前提交和修复的。因此,在进一步挖掘之后,我发现,在 MacOS 上,捆绑的 jre (../jre/Contents/Home/jre/lib/jspawnhelper) 中有一个可执行文件,需要可执行文件才能使 Runtime.exec() 工作。它不是,但只要我让它可执行我的进程 运行 就没有错误。

为了使其可执行,我将其添加到捆绑 jre 的 build.properties 文件中:

root.macosx.cocoa.x86_64.permissions.755=jre/Contents/Home/jre/lib/*

您可能需要根据您的 arch 和 jre 位置对该行进行调整。