当前位置: 首页 > 面试题库 >

如何从java.lang.Process关闭适当的std流?

仲皓君
2023-03-14
问题内容

这个问题是关于java.lang.Processstdin,stdout和stderr及其处理的。

我们的项目中有一个课程是对的扩展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流?或者可能我想念关闭之前由过程返回流getInputStream()getOutputStream()getErrorStream()方法呢?

在StackOverflow.com上有一个相关的问题:java:关闭子进程std流?

编辑

正如我和其他人在这里指出的那样:

  • InputStreams必须被完全消耗。如果未完成,则子进程可能不会终止,因为其输出流中有未完成的数据。
  • 所有三个标准流都必须关闭。不管是否使用过。
  • 当子进程正常终止时,一切都会正常。如果没有,则必须强制终止。
  • 当子进程返回退出代码时,我们就不需要destroy()它了。它已终止。(即使不一定必须以退出代码0正常终止,但也终止了。)
  • 我们需要监视waitFor()并在超时超过时中断,以使进程有机会正常终止,但在挂起时将其杀死。

未回答的部分:

  • 考虑并行使用InputStream的利弊。还是必须按特定顺序消费它们?

问题答案:

只是让您知道我目前在我们的代码库中:

public static void close(@Nullable Process process) throws IOException {
  if (process == null) {
    return;
  }

  Throwable t = null;

  try {
    flushQuietly(process.getOutputStream());
  }
  catch (Throwable e) {
    t = mostImportantThrowable(t, e);
  }

  try {
    close(process.getOutputStream());
  }
  catch (Throwable e) {
    t = mostImportantThrowable(t, e);
  }

  try {
    skipAllQuietly(null, TIMEOUT, process.getInputStream());
  }
  catch (Throwable e) {
    t = mostImportantThrowable(t, e);
  }

  try {
    close(process.getInputStream());
  }
  catch (Throwable e) {
    t = mostImportantThrowable(t, e);
  }

  try {
    skipAllQuietly(null, TIMEOUT, process.getErrorStream());
  }
  catch (Throwable e) {
    t = mostImportantThrowable(t, e);
  }

  try {
    close(process.getErrorStream());
  }
  catch (Throwable e) {
    t = mostImportantThrowable(t, e);
  }

  try {
    try {
      Thread monitor = ThreadMonitor.start(TIMEOUT);
      process.waitFor();
      ThreadMonitor.stop(monitor);
    }
    catch (InterruptedException e) {
      t = mostImportantThrowable(t, e);
      process.destroy();
    }
  }
  catch (Throwable e) {
    t = mostImportantThrowable(t, e);
  }

  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);
  }
}

skipAllQuietly(...)消耗完整的InputStreams。org.apache.commons.io.ThreadMonitor如果超过给定的超时,它在内部使用类似于中断消耗的实现。

mostImportantThrowable(...)决定应返回哪些Throwable。错误遍及一切。第一次发生的高优先级比后来发生的高。这里没有什么很重要的,因为这些Throwable最有可能在以后被丢弃。我们想继续在这里工作,我们只能扔一个,所以如果有的话,我们必须决定最后扔什么。

close(...) 是用于关闭内容的null安全实现,但是在出现问题时抛出Exception。



 类似资料:
  • 原关闭原因未解决 我有一个由多个Maven子项目组成的项目。结构是这样的 在文件夹脚本中,我有启动子项目的shell脚本,即。 我想这样做,shell脚本中的版本(方括号内)将在子项目[n]pom中更改版本后更新。xml。 实现目标的标准方法是什么?

  • 在我设法为我的类类型重载之后,我现在想要专门化它,而不是重载它,因为标准允许向名称空间添加模板专门化。下面是我的例子: 我不知道为什么它没有编译,并且我得到了一个错误:

  • 问题内容: 方法waitFor()返回一个整数值,该整数值是返回码。值0表示正常终止。但是其他返回码的含义是什么?我获得退出值11.这是什么意思?在哪里记录了所有退出值代码? 问题答案: 这些值是任意的,并取决于要定义的特定程序。您应该参考输出此退出代码的程序的文档或源代码。

  • 我有一个Jframe(美因茨), 它有一个按钮(showDialog), 当用户单击该按钮时, jdialog (Dialogz) 将显示, 那个jdialog有一个按钮 如何从该按钮关闭jdialog(在jdialog内部)? 我可以在创建对话框的实例后更改对话框的模式吗? 我需要阻止jdialog的所有者 我试着。。。 非常感谢你的任何帮助

  • 下面的代码显示了我要做的: