这个问题是关于java.lang.Process
及其对 stdin、stdout 和 stderr 的处理。
我们的项目中有一个类是对org.apache.commons.io.IOUtils
。我们有一个安静的新方法来关闭进程对象的标准流吗?还是不合适?
/**
* 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 流?或者我可能会错过关闭之前由进程返回的流'getInputStream()
, getOutputStream()
and getErrorStream()
方法?
StackOverflow.com 上有一个相关问题:java:关闭子进程std流?
Edit
正如我和其他人在这里指出的:
- 输入流必须被完全消耗。如果不完成,则子进程可能不会终止,因为其输出流中存在未完成的数据。
- 所有三个标准流都必须关闭。不管以前用过还是没用过。
- 当子进程正常终止时,一切都应该没问题。如果不是,则必须强制终止。
- 当子进程返回退出代码时,我们不需要
destroy()
它。它已经终止了。 (即使不一定以退出代码 0 正常终止,但它还是终止了。)
- 我们需要监控
waitFor()
并在超时时中断,以便进程有机会正常终止,但在挂起时杀死它。
未答复部分:
- 考虑并行使用 InputStream 的优点和缺点。或者它们必须按特定顺序消耗?