【问题标题】:Java Process "The pipe has been ended" problemJava进程“管道已结束”问题
【发布时间】:2014-07-31 15:36:29
【问题描述】:

我正在使用 Java Process API 编写一个类,该类从网络接收二进制输入(例如通过 TCP 端口 A),对其进行处理并将二进制输出写入网络(例如通过 TCP 端口 B)。我正在使用 Windows XP。代码看起来像这样。有两个函数称为run()receive():在开始时调用一次run,而只要通过网络接收到新的输入,就会调用receive。运行和接收是从不同的线程调用的。

run进程启动一个exe并接收exe的输入输出流。 Run 还会启动一个新线程,将 exe 的输出写入端口 B。

    public void run() {
        try {
            Process prc = // some exe is `start`ed using ProcessBuilder
                    OutputStream procStdIn = new BufferedOutputStream(prc.getOutputStream());
            InputStream procStdOut = new BufferedInputStream(prc.getInputStream());
                    Thread t = new Thread(new ProcStdOutputToPort(procStdOut));
                    t.start();

                    prc.waitFor();
                    t.join();
                    procStdIn.close();
                    procStdOut.close();
        } catch (Exception e) {
            e.printStackTrace();
            printError("Error : " + e.getMessage());
        }
    }

receive 将接收到的输入从端口 A 转发到 exe。

    public void receive(byte[] b) throws Exception {
        procStdIn.write(b);
    }

    class ProcStdOutputToPort implements Runnable {
        private BufferedInputStream bis;
        public ProcStdOutputToPort(BufferedInputStream bis) {
            this.bis = bis;
        }
        public void run() {
            try {
                int bytesRead;
                int bufLen = 1024;
                byte[] buffer = new byte[bufLen];
                while ((bytesRead = bis.read(buffer)) != -1) {
                    // write output to the network
                }
            } catch (IOException ex) {
                Logger.getLogger().log(Level.SEVERE, null, ex);
            }
        }
    }

问题是我在receive() 中得到了以下堆栈,然后prc.waitfor() 立即返回。行号显示堆栈正在写入 exe。

 The pipe has been ended
 java.io.IOException: The pipe has been ended
 at java.io.FileOutputStream.writeBytes(Native Method)
 at java.io.FileOutputStream.write(FileOutputStream.java:260)
 at java.io.BufferedOutputStream.write(BufferedOutputStream.java:105)
 at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
 at java.io.BufferedOutputStream.write(BufferedOutputStream.java:109)
 at java.io.FilterOutputStream.write(FilterOutputStream.java:80)
 at xxx.receive(xxx.java:86)

对此的任何建议将不胜感激。

【问题讨论】:

    标签: java process


    【解决方案1】:

    这意味着您在另一端已经关闭管道之后写入管道。

    这表明您的应用程序协议中存在重大错误。

    【讨论】:

    • 封闭管道是用来写入exe进程的管道。所以有问题的协议是 Java Process API。
    • Java Process API 没有 协议。 “已经关闭它的另一端”是您执行的过程。因此,在进程停止读取后,您正在向进程写入内容。所以有问题的协议是你的应用程序和你正在执行的进程之间的协议
    • 这很奇怪,因为我已经使用命令提示符测试了 java 之外的其他进程,并且在那里运行良好。似乎java代码中有一些错误。感谢您的 cmets。
    • 当您在关闭输入后尝试写入另一个进程时发生了什么?你是怎么测试的。你测试了吗?你需要明白这一点。写入已被对等方关闭的管道或套接字总是会产生错误条件并且总是错误的。
    • 是的,我知道写入由对等方关闭的管道是错误的。不,我没有测试你描述的场景。但这是不应该发生的事情:被执行的进程不应该在中间停止读取。在命令行上它不会在中间停止读取,所以我不明白为什么它在执行时会在中间停止读取。
    【解决方案2】:

    我最近遇到了同样的问题,我找到了解决方案。

    首先,“管道已结束”错误不是Java错误-它来自Windows系统。根据 MSDN:

    使用进程已关闭管道,或者,如果您正在尝试编写 到管道,没有可用的阅读器。

    信息量不大。但是,如果进程自己关闭了管道,则可能意味着进程发生了一些错误

    要检查这一点,请将来自进程的错误重定向到文件:

    File f = new File("errors.txt");
    pb.redirectError(f);
    

    就我而言(我一直在尝试执行 SrcML 解析器)文件包含以下内容:

    .\libs\srcML-Win\src2srcml.exe: unrecognised option `--language Java'
    Try 'src2srcml --help' for more information.
    

    解决了这个问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-02
      • 2013-03-28
      • 1970-01-01
      • 2018-11-23
      • 2019-12-30
      • 1970-01-01
      • 1970-01-01
      • 2022-10-06
      相关资源
      最近更新 更多