首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Java Runtime.exec() 卡住不執行:readLine() 重複呼叫導致阻塞

     編輯:程式設計綜合問答

問題現象

伺服端程式碼中:

System.out.println(is.readLine());          // 第一次讀取
Runtime.getRuntime().exec(is.readLine());   // 第二次讀取 → 永久阻塞

執行到 exec() 時程式停住,無錯誤、無後續輸出。

根本原因

BufferedReader.readLine() 會消耗輸入流資料。第一次呼叫已將指令字串(如 "cmd /k start E://test.txt")讀走並列印,第二次呼叫時流中已無資料,導致 readLine() 陷入「等待新資料」的阻塞狀態,exec() 根本未被呼叫。

正確寫法

String command = is.readLine();   // 唯一讀取一次
System.out.println("Received: " + command);
Runtime.getRuntime().exec(command); // 使用已讀取的變數

其他程式碼缺失與修正

問題修正
String line = null; 直接進入 while(!line.equals("bye")) 拋 NPE初始化 String line = ""; 或改用 while(true) 內部 break
使用 BufferedReader 需客戶端送 \r\n 才能讀取完整行改用 InputStream.read() 讀取原始位元組,或協定約定換行符
未處理 exec() 回傳的 Process 物件取得 Process p = Runtime.getRuntime().exec(...),讀取 p.getInputStream()/getErrorStream() 避免緩衝區滿死鎖

完整修正範例

public class Server {
    public static void main(String[] args) {
        try (ServerSocket sersoc = new ServerSocket(8399);
             Socket socket = sersoc.accept();
             BufferedReader is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
             PrintWriter os = new PrintWriter(socket.getOutputStream(), true);
             BufferedReader sin = new BufferedReader(new InputStreamReader(System.in))) {

            String command = is.readLine(); // 讀取指令
            System.out.println("Command: " + command);
            if (command != null) {
                Process p = Runtime.getRuntime().exec(command);
                // 非同步消耗輸出/錯誤流,防止死鎖
                new Thread(() -> consume(p.getInputStream())).start();
                new Thread(() -> consume(p.getErrorStream())).start();
                p.waitFor();
            }

            String line;
            while ((line = sin.readLine()) != null) {
                os.println(line);
                System.out.println("Server: " + line);
                String clientMsg = is.readLine();
                if (clientMsg == null || "bye".equalsIgnoreCase(clientMsg)) break;
                System.out.println("Client: " + clientMsg);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    static void consume(InputStream is) {
        try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
            String l; while ((l = br.readLine()) != null) System.out.println(l);
        } catch (IOException ignored) {}
    }
}

掌握「一次讀取、存變數、再使用」原則,並妥善處理 Process 流與阻塞邊界,即可避免 Runtime.exec() 卡死陷阱。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved