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

Java 監控系統進程兩大方案:Runtime.exec 與 JNI 深度解析

     編輯:Java 相關知識

需求:在同一台 Windows x86 機器上,由第一個 JVM 啟動第二個 JVM 執行測試程式,並由第一個 JVM 的 Java 程式監控第二個 JVM 的記憶體與 CPU 使用情況,以比較不同程式在相同 JVM 環境下的資源消耗差異。

方案一:Runtime.exec + 系統命令(純 Java,簡單實用)

核心思路

  1. 使用 Runtime.getRuntime().exec() 啟動第二個 JVM 執行目標程式。
  2. 使用 Windows 內建 tasklist 命令將進程資訊導出至文字檔。
  3. 第一個 JVM 讀取並解析該檔案,提取目標 JVM 進程的記憶體/CPU 數據。

關鍵代碼實現

// 1. 啟動第二個 JVM 執行測試程式
Runtime rt = Runtime.getRuntime();
String[] cmdStart = { "C:\\jdk1.8\\jre\\bin\\java", "-cp", "test.jar", "com.test.Main" };
Process proc = rt.exec(cmdStart);

// 2. 定期執行 tasklist 導出進程快照
String[] cmdTasklist = { "cmd", "/c", "tasklist /fo csv /nh > process_log.csv" };
rt.exec(cmdTasklist);

// 3. 解析 CSV 檔案,提取目標進程(PID 或映像名稱)的 Mem Usage、CPU Time
//    可使用 BufferedReader 逐行讀取,String.split(",") 分欄位

優缺點分析

優點缺點
純 Java,無需原生庫,跨平台潛力大(換命令即可)輪詢間隔導致數據非即時,精度受限於 tasklist 更新頻率
實現極簡,幾行代碼即可完成核心功能需處理 CSV 解析、PID 追蹤、子進程管理等邊界情況
不侵入被測程式,無副作用大量進程時 I/O 開銷明顯

方案二:JNI (Java Native Interface) + 原生代理(高精度、高複雜度)

架構設計

  • Java 層:定義 native 方法,載入共享庫(.dll/.so)。
  • C/C++ 層:實現 JNI 函數,呼叫 Windows API(OpenProcess, GetProcessMemoryInfo, GetProcessTimes)精準讀取進程記憶體、CPU 時間。
  • 可選:編寫 C# 監控元件透過 JNI 橋接,利用 .NET System.Diagnostics.Process 類簡化開發。

關鍵 JNI 代碼片段

// Java 宣告
public class ProcessMonitor {
    static { System.loadLibrary("procmon"); }
    public native long getMemoryUsage(int pid);
    public native double getCpuUsage(int pid);
}

// C++ 實現 (Windows)
#include 
#include 
#include 

JNIEXPORT jlong JNICALL Java_ProcessMonitor_getMemoryUsage(JNIEnv *env, jobject obj, jint pid) {
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
    if (!hProcess) return -1;
    PROCESS_MEMORY_COUNTERS pmc;
    if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc))) {
        CloseHandle(hProcess);
        return pmc.WorkingSetSize; // 實體記憶體使用量
    }
    CloseHandle(hProcess);
    return -1;
}

C# 替代方案(降低 C++ 複雜度)

編寫 C# 類庫(ProcessMonitorLib.dll)封裝 System.Diagnostics.Process,再透過 JNI4NET 或自訂 COM/管道 互操作,Java 呼叫 C# 方法獲取數據。但需注意:被測 JVM 若自身使用 JNI,可能觸發衝突導致數據不準;若僅做相對比較且被測程式無 JNI 調用,此方案可行。

優缺點分析

優點缺點
毫秒級精度,可獲取私有/虛擬記憶體、核心/使用者 CPU 時間等細粒度指標需編寫/編譯原生代碼,部署需攜帶平台相關動態庫
無輪詢延遲,事件驅動可行JNI 開發門檻高,易發生崩潰導致 JVM 退出
可整合更多系統級指標(句柄數、執行緒數、I/O 計數器)跨平台移植需重寫原生層

方案選型建議

  • 快速原型、相對比較、低頻採樣:首選方案一,開發效率最高。
  • 生產級監控、精準調優、需綜合指標:投入方案二,或直接採用成熟 APM 工具(VisualVM, JProfiler, Arthas, Prometheus+JMX Exporter)。
  • 混合策略:方案一做常態巡檢,方案二做關鍵時段深度剖析。

總結

Java 監控外部 JVM 進程,Runtime.exec + tasklist 是輕量級首選;JNI 提供極致精度但複雜度高。實務中多建議直接使用標準化觀測體系(JMX, Micrometer, OpenTelemetry)植入應用內部,避免外部採樣的固有盲區與干擾。

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