使用ProcessBuilder获取进程流时遇阻塞问题求助
问题原因与解决方法
你的代码卡在readLine()的核心原因是命令中使用了start关键字:
start java -jar application.jar会让cmd.exe启动一个全新的独立进程来运行Java程序,而你通过ProcessBuilder启动的原cmd进程,在执行完start命令后就直接退出了。- 原进程的输入流没有任何输出内容,导致
BufferedReader.readLine()一直阻塞,等待永远不会到来的输入数据。
解决方案1:移除start命令(推荐)
去掉start后,Java程序会在ProcessBuilder创建的进程中运行,其输出会直接流入你创建的BufferedReader,这样就能正常读取内容:
修改命令常量
public static String START_APPLICATION_MANAGER_COMMAND = "cd /D %VARENV%/../Application && java -jar application.jar";
更优雅的写法(直接设置工作目录)
没必要用cd命令,ProcessBuilder支持直接设置进程工作目录,避免环境变量解析或路径拼接问题:
public static void startApplicationManager() throws Exception { // 解析环境变量VARENV,获取Application目录的绝对路径 String varEnvPath = System.getenv("VARENV"); File applicationDir = new File(new File(varEnvPath).getParent(), "Application"); // 直接构造Java启动命令,设置工作目录 ProcessBuilder builder = new ProcessBuilder("java", "-jar", "application.jar"); builder.directory(applicationDir); builder.redirectErrorStream(true); // 合并错误流到输入流 ProcessManager.executeCommandOnLocalMachine(builder); }
解决方案2:保留新窗口同时捕获输出(复杂场景)
如果必须在新窗口运行Java程序,又要捕获输出,可以将Java程序的输出重定向到文件,然后通过读取文件内容来获取日志:
public static String START_APPLICATION_MANAGER_COMMAND = "cd /D %VARENV%/../Application && start java -jar application.jar > app.log 2>&1";
之后你需要单独编写代码读取app.log文件的内容,注意处理文件写入的实时性问题(比如轮询文件变化)。
额外注意事项
- 确保Java程序的输出带有换行符:
readLine()必须等待换行符才会返回,如果你的Java程序输出没有换行,同样会导致阻塞。可以改用reader.read()读取单个字符,或者设置超时逻辑。 - 处理进程阻塞:如果Java程序长时间运行,你的当前线程会一直卡在循环中,建议将读取输入流的逻辑放到单独的线程中执行,避免阻塞主线程。
内容的提问来源于stack exchange,提问作者Rafale_Scarlet
相关产品推荐
相关产品推荐

