【发布时间】:2011-10-27 06:17:30
【问题描述】:
这个问题是关于java.lang.Process 及其对标准输入、标准输出和标准错误的处理。
我们的项目中有一个类是org.apache.commons.io.IOUtils 的扩展。我们有一种安静的新方法可以适当地关闭 Process-Object 的标准流吗?还是不合适?
/**
* 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-blocks中。
我真正想知道的是我是否可以安全地使用此实现?考虑以下事项:进程对象在其生命周期内是否总是返回相同的标准输入、标准输出和标准错误流?或者我可能会错过关闭之前由进程'getInputStream()、getOutputStream() 和getErrorStream() 方法返回的流?
StackOverflow.com 上有一个相关问题:java: closing subprocess std streams?
编辑
正如我和其他人在这里指出的:
- InputStreams 必须被完全消耗掉。如果未完成,则子进程可能不会终止,因为其输出流中有未完成的数据。
- 必须关闭所有三个标准流。不管之前是否使用过。
- 当子进程正常终止时,一切都应该没问题。如果没有,则必须强制终止。
- 当子进程返回退出代码时,我们不需要
destroy()它。它已终止。 (即使不一定以退出代码 0 正常终止,但它已终止。) - 我们需要监控
waitFor(),并在超时时间超过时中断,让进程有机会正常终止,但在挂起时将其杀死。
未回答的部分:
- 考虑并行使用 InputStream 的优缺点。还是必须按特定顺序食用?
【问题讨论】:
-
只是一个注释。您的代码中有一些严重的反模式。 1. 尝试/捕捉几乎每一条语句。 2. 每次都能捕捉到所有“可投掷”的东西。 3.嵌套的try语句也可以是一个,两个catch语句。
-
不将其他流放入单独的 try-catch 块时,如何继续关闭其他流?
-
嵌套的 try-catch-block 必须是,因为 Throwable 可以出现在嵌套的 catch-block 中。对于追星
Throwable:什么更合适?我想抓住一切值得继续努力的事情,以尽我最大的努力关闭资源。之前被抓到时,我在最后扔了一个 Throwables。我可以在这里做得更好吗? -
请注意,这是一个实用程序类,用于关闭其他地方的 finally 块中的资源。处理异常不是它的工作。它抛出第一个发生的异常。调用者必须处理它。但它的意图是尽一切可能释放调用者提供的资源。
标签: java process stream resources