You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为通过Runtime.getRuntime.exec()调用的Java程序传递输入

问题根因

  • 第一,runProcess.waitFor()的调用时机错误:你在给子进程传输入、读取子进程输出之前就等待子进程退出,此时子进程正阻塞等待输入,永远不会退出,直接形成死锁。
  • 第二,存在多处未声明的变量:pathJava、op都没有定义,代码本身无法编译通过。
  • 第三,未处理子进程的错误流:子进程运行/编译时的错误输出会填满缓冲区,导致子进程主动阻塞。
  • 第四,输入流关闭时机错误:刚写入一次输入就关闭输出流,无法支持多次输入场景,且写入后没有刷缓,数据可能停留在缓冲区没有传给子进程。

修正后代码

import java.io.*;
import java.util.Scanner;

public class Example {
    public static void main(String[] args) {
        try {
            // 修正变量名错误
            String pathJava = "src/main/java/SampleProg.java";
            compile(pathJava);
            Process runProcess = run();

            // 获取子进程的输入流(我们给子进程写输入用这个)、输出流、错误流
            BufferedWriter op = new BufferedWriter(new OutputStreamWriter(runProcess.getOutputStream()));
            BufferedReader processOut = new BufferedReader(new InputStreamReader(runProcess.getInputStream()));
            BufferedReader processErr = new BufferedReader(new InputStreamReader(runProcess.getErrorStream()));
            Scanner sc = new Scanner(System.in);

            // 单独开线程处理子进程的输出,避免阻塞
            new Thread(() -> {
                try {
                    String s;
                    while ((s = processOut.readLine()) != null) {
                        System.out.println("子进程输出:" + s);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();

            // 单独开线程处理子进程的错误输出,避免缓冲区满阻塞
            new Thread(() -> {
                try {
                    String s;
                    while ((s = processErr.readLine()) != null) {
                        System.err.println("子进程错误:" + s);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();

            // 主线程处理用户输入,传给子进程
            while (sc.hasNextLine()) {
                String input = sc.nextLine();
                op.write(input);
                op.newLine(); // 换行对应子进程readLine()的结束标记
                op.flush(); // 强制刷缓,确保数据传给子进程
                // 如果是结束输入的标记(比如输入exit就退出)可以在这里加判断关闭流
                if ("exit".equalsIgnoreCase(input)) {
                    op.close();
                    break;
                }
            }

            // 所有输入输出处理完再等待子进程退出
            int exitCode = runProcess.waitFor();
            System.out.println("子进程执行结束,退出码:" + exitCode);

            sc.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void compile(String pathJava) throws IOException, InterruptedException {
        String[] cmd = new String[4];
        cmd[0] = "javac";
        cmd[1] = "-d";
        cmd[2] = ".";
        cmd[3] = pathJava;
        Process compileProcess = Runtime.getRuntime().exec(cmd);
        // 编译时也要处理输出和错误流,避免编译出错时阻塞
        printStream(compileProcess.getInputStream(), System.out);
        printStream(compileProcess.getErrorStream(), System.err);
        int exitCode = compileProcess.waitFor();
        if (exitCode != 0) {
            throw new RuntimeException("编译失败,退出码:" + exitCode);
        }
    }

    private static Process run() throws IOException {
        String[] cmd = new String[2];
        cmd[0] = "java";
        cmd[1] = "SampleProg";
        return Runtime.getRuntime().exec(cmd);
    }

    // 工具方法:打印进程流内容
    private static void printStream(InputStream in, PrintStream out) {
        new Thread(() -> {
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    out.println(line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

关键修改说明

  • 调整waitFor()的调用时机,等所有输入输出交互完成后再等待进程退出
  • 新增单独线程处理子进程的标准输出、错误输出,避免缓冲区满导致的进程阻塞
  • 补全所有缺失的变量声明和流初始化逻辑
  • 输入写入后新增换行和刷缓操作,确保子进程可以正常识别输入结束
  • 编译阶段新增错误判断和流处理,提前感知编译失败的问题

内容的提问来源于stack exchange,提问作者Aahlad Kethineedi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 05:45:05