process.waitFor()永远不会返回
Process process = Runtime.getRuntime().exec("tasklist"); BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); process.waitFor();
waitFor()
不返回有很多原因。
但通常归结为执行的命令不会退出。
这也可以有很多原因。
一个常见的原因是这个过程产生了一些输出,而你并没有从适当的stream中读取。 这意味着只要缓冲区已满,进程就会被阻止,并等待进程继续读取。 你的进程轮stream等待另一个进程完成(这不会因为它等待你的进程,…)。 这是一个典型的死锁情况。
您需要不断从stream程inputstream中读取,以确保不会阻止。
有一篇很好的文章,解释了Runtime.exec()
所有缺陷,并且展示了他们周围的一种叫做“当Runtime.exec()不会” (是的,文章是从2000年开始的,但内容仍然适用!
看来在等待它完成之前你并没有读取输出。 这只有在输出不能填充缓冲区的情况下才行。 如果是这样,它会等到你读到输出,catch-22。
也许你有一些你没有阅读的错误。 这会使应用程序停止并等待永久等待。 解决这个问题的一个简单方法是将错误重新定向到正常输出。
ProcessBuilder pb = new ProcessBuilder("tasklist"); pb.redirectErrorStream(true); Process process = pb.start(); BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); String line; while ((line = reader.readLine()) != null) System.out.println("tasklist: " + line); process.waitFor();
另外从Java文档:
java.lang中
类过程
由于某些本地平台仅为标准input和输出stream提供有限的缓冲区大小,因此如果不及时写入inputstream或读取子stream程的输出stream,可能会导致subprocess阻塞甚至死锁。
无法清除Process中inputstream的缓冲区(从哪个pipe道到子stream程的输出stream)可能会导致子stream程阻塞。
尝试这个:
Process process = Runtime.getRuntime().exec("tasklist"); BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); while ((reader.readLine()) != null) {} process.waitFor();
我想补充一些以前的答案,但由于我没有代表评论,我只会添加一个答案。 这是针对用Java编程的android用户。
根据RollingBoy的post,这段代码几乎适用于我:
Process process = Runtime.getRuntime().exec("tasklist"); BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); while ((reader.readLine()) != null) {} process.waitFor();
在我的情况下,waitFor()没有释放,因为我正在执行一个没有返回的语句(“ip adddr flush eth0”)。 解决这个问题的简单方法是简单地确保你总是在你的陈述中返回一些东西。 对我来说,这意味着执行以下操作:“ip adddr flush eth0 && echo done”。 你可以整天读缓冲区,但是如果没有任何东西返回,你的线程将永远不会释放它的等待。
希望帮助别人!
有几种可能性:
- 您还没有使用该进程的
stdout
上的所有输出。 - 你没有消耗进程的所有输出。
- 这个过程正在等待你的input ,而你还没有提供,或者你还没有closures过程的
stdin
。 - 这个过程在一个艰难的循环中旋转。
出于同样的原因,您还可以使用inheritIO()
将Java控制台与外部应用程序控制台进行映射,如下所示:
ProcessBuilder pb = new ProcessBuilder(appPath, arguments); pb.directory(new File(appFile.getParent())); pb.inheritIO(); Process process = pb.start(); int success = process.waitFor();
我认为我观察到类似的问题:一些进程开始,似乎运行成功,但从来没有完成。 函数waitFor()正在等待,除非我在任务pipe理器中终止了进程。
但是,如果命令行长度不超过127个字符,则一切正常。 如果长文件名是不可避免的,你可能想使用环境variables,这可能会让你保持命令行string的简短。 你可以生成一个batch file(使用FileWriter),在其中设置你的环境variables,然后调用你真正想要运行的程序。 这样一批的内容可能如下所示:
set INPUTFILE="C:\Directory 0\Subdirectory 1\AnyFileName" set OUTPUTFILE="C:\Directory 2\Subdirectory 3\AnotherFileName" set MYPROG="C:\Directory 4\Subdirectory 5\ExecutableFileName.exe" %MYPROG% %INPUTFILE% %OUTPUTFILE%
最后一步是使用Runtime运行这个batch file。
正如其他人所说,你必须消费stderr和stdout 。
与其他答案相比,自Java 1.7以来,它更容易。 您不必自己创build线程来阅读stderr和stdout 。
只需使用ProcessBuilder
,并将redirectOutput
方法与redirectError
或redirectErrorStream
结合使用即可。
String directory = "/working/dir"; File out = new File(...); // File to write stdout to File err = new File(...); // File to write stderr to ProcessBuilder builder = new ProcessBuilder(); builder.directory(new File(directory)); builder.command(command); builder.redirectOutput(out); // Redirect stdout to file if(out == err) { builder.redirectErrorStream(true); // Combine stderr into stdout } else { builder.redirectError(err); // Redirect stderr to file } Process process = builder.start();