在 Java 開發中,有時需要與底層作業系統交互,例如獲取當前系統正在運行的進程列表。Java 標準庫並未直接提供跨平台的進程管理 API,但我們可以通過 ProcessBuilder 啟動系統命令(如 Windows 的 tasklist 或 Linux 的 ps -ef),並解析其輸出流來實現該需求。本文提供一個基於 Windows 環境的完整代碼示例。
package com.wa.xwolf.sblog.util;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
public class ProcessUtil {
public static void main(String[] args) throws Exception {
// 1. 構建系統進程,Windows 下使用 tasklist 命令
ProcessBuilder pb = new ProcessBuilder("tasklist");
Process p = pb.start();
// 2. 處理輸出流:Windows 控制台預設編碼通常為 GB2312 (或 GBK)
BufferedReader out = new BufferedReader(
new InputStreamReader(
new BufferedInputStream(p.getInputStream()),
Charset.forName("GB2312")
)
);
// 3. 處理錯誤流(防止緩衝區填滿導致阻塞)
BufferedReader err = new BufferedReader(
new InputStreamReader(new BufferedInputStream(p.getErrorStream()))
);
System.out.println("=== Windows 系統進程列表 ===");
String line;
while ((line = out.readLine()) != null) {
System.out.println(line);
}
String errLine = err.readLine();
if (errLine != null) {
System.out.println("\n--- Error Info ---");
System.out.println(errLine);
}
}
}
ProcessBuilder 是 JDK 1.5 引入的更現代化 API,支援列表形式傳遞命令參數,自動處理空格、特殊字符轉義,且能靈活設置工作目錄、環境變量、合併錯誤流等,建議優先使用。
Windows cmd 默認編碼為 GB2312/GBK,Linux/Mac 為 UTF-8。若直接使用系統默認編碼讀取流,中文進程名極大概率會出現亂碼。代碼中顯式指定 Charset.forName("GB2312") 是保證中文正常顯示的關鍵。
子進程的標準錯誤流若不被讀取,緩衝區填滿會導致子進程阻塞甚至掛起。即使不關心錯誤信息,也必須開啟線程或在主線程中消費 getErrorStream()。
若需跨平台,可封裝工具類,根據 System.getProperty("os.name") 動態選擇命令:
tasklist 或 tasklist /fo csv (CSV 格式易解析)ps -ef 或 ps aux=== Windows 系統進程列表 ===
映像名稱 PID 會話名 會話# 記憶體使用
========================= ======== ================ =========== ============
System Idle Process 0 Services 0 8 K
System 4 Services 0 340 K
Registry 96 Services 0 8,208 K
smss.exe 388 Services 0 1,200 K
...
java.exe 1234 Console 1 45,678 K
cmd.exe 5678 Console 1 3,456 K
tasklist /v /fo csv 解析 CPU、記憶體佔用。netstat -ano 定位佔用端口的 PID,再查進程詳情。通過 ProcessBuilder 調用系統原生命令,配合正確的流讀取與編碼轉換,即可輕鬆在 Java 中獲取本地進程列表。實際生產中建議封裝為通用工具類,處理異常、超時、跨平台差異,提升穩健性。