首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 調用系統命令完全指南:Runtime.exec 避坑與最佳實踐

     編輯:Java 相關知識

基礎模式:Runtime.exec + Process 控制

Process process = Runtime.getRuntime().exec(".\\p.exe");
process.waitFor(); // 等待子進程結束

exec() 創建子進程,返回 Process 對象控制其生命週期。waitFor() 阻塞當前線程直到子進程退出。

Windows 平台四大避坑指南

1. 執行 DOS 內部命令(dir、copy、del 等)

內部命令屬於命令解釋器,不能直接執行。兩種方案:

  • 包裝命令解釋器:
    // Windows NT/2000/XP/7/10
    Runtime.getRuntime().exec("cmd.exe /c dir");
    // Windows 95/98 (歷史)
    Runtime.getRuntime().exec("command.exe /c dir");
    
    /c 參數:執行完畢關閉窗口。跨平台需檢測 OS 版本動態選擇。
  • 寫入 .bat 批處理文件:exec("my_dir.bat"),無需關心解釋器差異,移植性更好。

❌ 直接 exec("dir") 會拋異常。

2. 打開關聯文件(如 .doc、.pdf、.txt)

利用系統文件關聯,兩種寫法:

// 方案 1:start 命令(推薦,簡潔)
Runtime.getRuntime().exec("start .\\a.doc");

// 方案 2:指定完整程序路徑(脆弱,路徑易變)
Runtime.getRuntime().exec("C:\\Program Files\\Microsoft Office\\Office\\winWord.exe .\\a.doc");

3. 處理有標準輸出的控制台程序——防死鎖核心

現象:子進程輸出過多,緩衝區填滿 → 進程阻塞 → waitFor() 永不返回 → 主程序掛死。
根因:Java 未及時讀取子進程 stdout/stderr 緩衝區。
解決:waitFor() 前務必消費輸出流:

Process process = Runtime.getRuntime().exec("cmd /c dir \\Windows");
BufferedReader reader = new BufferedReader(
    new InputStreamReader(process.getInputStream())
);
String line;
while ((line = reader.readLine()) != null) {
    System.out.println(line); // 或寫日志、丟棄
}
process.waitFor(); // 此刻緩衝區已空,安全返回

進階:同時消費 getErrorStream(),建議用獨立線程讀取雙流,防單流塞滿死鎖。

4. 刪除文件實戰:資源佔用導致刪除失敗的流氓解法

場景:自動更新下載 ZIP → 解壓 → 刪除 ZIP。Java ZIP 流未關閉導致文件句柄佔用,常規 file.delete() 失敗。
暴力繞過:調用系統 del 命令(OS 層面強制刪除,不受 JVM 句柄限制):

// ✅ 正確:包裝 cmd /c
Runtime.getRuntime().exec("cmd /c del f:\\aaa.doc");

// ❌ 錯誤:直接 exec del(非可執行文件)
Runtime.getRuntime().exec("del f:\\aaa.doc");

⚠️ 注意:這是應急手段。正規做法是嚴格關閉所有流(try-with-resources)、使用 Files.deleteIfExists() (NIO.2)、或延遲刪除 (JVM 退出鉤子)。

最佳實踐總結

場景推薦做法關鍵點
外部可執行程序Runtime.exec / ProcessBuilder異步讀雙流、超時控制、退出碼檢查
DOS 內部命令cmd /c command 或 .bat 文件跨版本兼容、路徑含空格加引號
打開關聯文件start filePath依賴系統關聯、無需硬編碼程序路徑
文件刪除失敗先查流關閉、再試 NIO.2、最後 cmd /c del治本優於治標、記錄日誌排查佔用者

現代替代方案:Java 7+ 推薦使用 ProcessBuilder(靈活配置環境變量、工作目錄、重定向)、Files API(文件操作)、Apache Commons Exec(高級進程控制)。

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