java - 使用 Java 运行外部命令时出现错误流阻塞

标签 java stream runtime.exec

在 SEAndroid 上工作时,我从 Java 应用程序调用 Setools 命令。 它与小型 SEAndroid 策略完美配合,现在我需要用真实的测试我的工具 SEAndroid 政策。但不幸的是,我遇到了错误流的问题。

这是我用来调用外部命令的代码:

public static BufferedReader runCommand(final String[] args)
            throws IOException {

    BufferedReader stdInput = null;
    BufferedReader stdError = null;
    try {
        Process p = Runtime.getRuntime().exec(args);

        stdInput = new BufferedReader(new
                InputStreamReader(p.getInputStream()));

        stdError = new BufferedReader(new
                InputStreamReader(p.getErrorStream()));

        // read any errors from the attempted command
        String s = null;
        StringBuilder err = new StringBuilder();

        while ((s = stdError.readLine()) != null) {
            err.append(s + "\n");
        }
        if (err.length() != 0) {
            throw new IOException(err.toString());
        }

        return stdInput;
    } finally {
        if (stdError != null) {
            stdError.close();
        }
    }
}

因此,如您所见,我调用了一个外部命令。然后读取错误流,如果有错误就抛出异常,否则我返回InputStream,以便稍后解析它。

使用真正的 SEAndroid 策略,错误流似乎会阻塞(即使我读取单个字符)并且我无法解析命令的结果。如果我关闭错误流而不读取任何内容,则应用程序可以正常工作,但我想处理错误(如果有)。 如果我在控制台中输入命令,它也可以正常工作。

在第一种情况下(使用较小的 SEAndroid 策略),命令的输出很小(约 350 行)。 在第二种情况下(使用真正的 SEAndroid 策略),命令的输出较大(>1500 行)。

输出流的大小是否可能影响错误流?这两个流是两个独特的资源,不是吗? 我没有立即读取输出流这一事实有重要性吗?

我担心这不是“编程”问题,而是系统问题......

有什么建议吗?

提前感谢您的帮助=)

编辑:

我尝试在错误流之前读取输出流并且它有效。但我需要在对输出流执行任何解析之前检查错误流,因此问题仍然是热门话题。

最佳答案

首先,最好使用较新的 ProcessBuilder类而不是运行时 exec。如果你想更进一步,你甚至可以使用 Apache commons-exec它会为您处理流处理和其他事情。

接下来,正如您所发现的,进程控制在 Java 中是一件棘手的事情,并且您已经遇到了它的棘手问题之一。来自java Process 类的文档:

The parent process uses these streams to feed input to and get output from the subprocess. Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, and even deadlock.

您需要有一些东西同时消耗(错误和输出)流,否则您将面临死锁的风险 - 这些都应该在自己的线程上读取。使用像 StreamGobbler 这样的东西(谷歌一下,那里有很多)将是一个很好的步骤,或者如果你愿意的话你也可以自己动手。正确执行并不难,但如果您不熟悉多线程,您可能需要查看其他人的实现或采用 Apache commons-exec 路线。

关于java - 使用 Java 运行外部命令时出现错误流阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23248824/

相关文章:

c# - 基于较长的流创建固定长度的流

c++ - 从 .txt 文件读取数据并放入 vector 时,Linux 比 Windows 快得多。我将如何加速 Windows 来做同样的事情?

ios - 多次使用后 AVPlayer 崩溃 - iOS

java - 从java代码获取cmd命令的输出

java - Spring框架中的回滚机制

java - 以编程方式创建布局以添加到 ViewPager?

java - StringBuilder 拆分的简单方法

java - StringUtils 拆分包含字符串的逗号问题

java - 通过 Java GUI 运行 Linux 命令

java - 代码在命令提示符中运行但不在 Eclipse 中运行