这个问题涉及到
我们的项目中有一个类,它是
java.lang.Process
以及其如何处理标准输入、标准输出和标准错误流。我们的项目中有一个类,它是
org.apache.commons.io.IOUtils
的扩展。在这个类中,我们新增了一个方法来安静地关闭Process-Object的std流。这样做是否合适?/**
* Method closes all underlying streams from the given Process object.
* If Exit-Code is not equal to 0 then Process will be destroyed after
* closing the streams.
*
* It is guaranteed that everything possible is done to release resources
* even when Throwables are thrown in between.
*
* In case of occurances of multiple Throwables then the first occured
* Throwable will be thrown as Error, RuntimeException or (masked) IOException.
*
* The method is null-safe.
*/
public static void close(@Nullable Process process) throws IOException {
if(process == null) {
return;
}
Throwable t = null;
try {
close(process.getOutputStream());
}
catch(Throwable e) {
t = e;
}
try{
close(process.getInputStream());
}
catch(Throwable e) {
t = (t == null) ? e : t;
}
try{
close(process.getErrorStream());
}
catch (Throwable e) {
t = (t == null) ? e : t;
}
try{
try {
if(process.waitFor() != 0){
process.destroy();
}
}
catch(InterruptedException e) {
t = (t == null) ? e : t;
process.destroy();
}
}
catch (Throwable e) {
t = (t == null) ? e : t;
}
if(t != null) {
if(t instanceof Error) {
throw (Error) t;
}
if(t instanceof RuntimeException) {
throw (RuntimeException) t;
}
throw t instanceof IOException ? (IOException) t : new IOException(t);
}
}
public static void closeQuietly(@Nullable Logger log, @Nullable Process process) {
try {
close(process);
}
catch (Exception e) {
//log if Logger provided, otherwise discard
logError(log, "Fehler beim Schließen des Process-Objekts (inkl. underlying streams)!", e);
}
}
public static void close(@Nullable Closeable closeable) throws IOException {
if(closeable != null) {
closeable.close();
}
}
这些方法基本上是在finally块中使用的。
我想知道的是,如果我使用这个实现是否安全?考虑到这样的事情:在其生命周期内,进程对象是否始终返回相同的stdin、stdout和stderr流? 或者说我可能错过了之前通过process的getInputStream()
、getOutputStream()
和getErrorStream()
方法返回的关闭流操作?
StackOverflow.com上有一个相关问题:java:关闭子进程std流?
编辑
正如我和其他人在这里指出的:
- 必须完全使用InputStreams。否则,子进程可能无法终止,因为其输出流中存在未完成的数据。
- 必须关闭所有三个std流。不管是否使用过。
- 当子进程正常终止时,一切都应该没问题。否则,必须强制终止。
- 当子进程返回退出代码时,我们不需要
destroy()
它。它已经终止了。(即使不一定是通过Exit Code 0正常终止,但它已经终止。) - 我们需要监视
waitFor()
,并在超时后中断,以便进程有机会正常终止,但在其挂起时将其杀死。
未回答的部分:
- 考虑并行消耗InputStreams的利弊。或者必须按特定顺序使用?