ProcessBuilder和Runtime.exec()之间的区别

我试图从java代码执行一个外部命令,但是我注意到了Runtime.getRuntime().exec(...)new Process(...).start()之间的区别。

使用Runtime

 Process p = Runtime.getRuntime().exec(installation_path + uninstall_path + uninstall_command + uninstall_arguments); p.waitFor(); 

exitValue为0,命令终止。

但是,使用ProcessBuilder

 Process p = (new ProcessBuilder(installation_path + uninstall_path + uninstall_command, uninstall_arguments)).start(); p.waitFor(); 

退出值是1001,命令终止在中间,虽然waitFor返回。

我该怎么办才能解决ProcessBuilder的问题?

Runtime.getRuntime().exec(...)的各种重载可以是一个string数组,也可以是一个string。 exec()的单个string重载将string标记为一个参数数组,然后将string数组传递给一个接受string数组的exec()重载。 另一方面, ProcessBuilder构造函数只采用可变长string数组或stringList ,其中数组或列表中的每个string被假定为单独的参数。 无论哪种方式,获得的参数然后join到传递给操作系统执行的string。

所以,例如,在Windows上,

 Runtime.getRuntime().exec("C:\DoStuff.exe -arg1 -arg2"); 

将使用两个给定的参数运行DoStuff.exe程序。 在这种情况下,命令行将被标记并放回到一起。 然而,

 ProcessBuilder b = new ProcessBuilder("C:\DoStuff.exe -arg1 -arg2"); 

将会失败,除非在C:\碰巧有名为DoStuff.exe -arg1 -arg2的程序。 这是因为没有标记:要运行的命令已经被标记。 相反,你应该使用

 ProcessBuilder b = new ProcessBuilder("C:\DoStuff.exe", "-arg1", "-arg2"); 

或者可选地

 List<String> params = java.util.Arrays.asList("C:\DoStuff.exe", "-arg1", "-arg2"); ProcessBuilder b = new ProcessBuilder(params); 

查看Runtime.getRuntime().exec()将String命令传递给ProcessBuilder 。 它使用一个标记器并将这个命令分解成单独的标记,然后调用构造一个ProcessBuilder exec(String[] cmdarray, ......)

如果你用一个string数组来构造ProcessBuilder而不是一个,你会得到相同的结果。

ProcessBuilder构造函数接受一个String... vararg,因此将整个命令作为单个String传递与在terminal中引用该命令的效果相同:

 shell$ "command with args" 

是的,有一个区别。

  • Runtime.exec(String)方法使用一个命令string将其分成一个命令和一系列参数。

  • ProcessBuilder构造函数接受一个(可变参数)string数组。 第一个string是命令名称,其余的是参数。

所以你告诉ProcessBuilder要做的是执行一个名字中有空格和其他垃圾的“命令”。 当然,操作系统找不到具有该名称的命令,命令执行失败。