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

在 Java 應用中監控 CPU 使用率:基於 JNI 的 Windows 實現

     編輯:J2SE

背景與挑戰

純 Java 無直接 API 獲取 CPU 使用率。常見替代方案:Runtime.exec() 呼叫 ps 解析 PID,但跨平台、效能、權限皆有問題。更可靠方案:JNI 呼叫原生 C 代碼 (Windows 示例)。

步驟 1:宣告 Native 方法

package com.vladium.utils;

public class SystemInformation {
    public static native long getProcessCPUTime(); // 返回進程已用 CPU 毫秒數
}

用 javah 產生 C 標頭:

JNIEXPORT jlong JNICALL Java_com_vladium_utils_SystemInformation_getProcessCPUTime
  (JNIEnv *env, jclass cls);

步驟 2:C 實現 (Win32)


#include 
static HANDLE s_currentProcess;
static int s_numberOfProcessors;

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
    SYSTEM_INFO si;
    s_currentProcess = GetCurrentProcess();
    GetSystemInfo(&si);
    s_numberOfProcessors = si.dwNumberOfProcessors;
    return JNI_VERSION_1_2;
}

JNIEXPORT jlong JNICALL Java_com_vladium_utils_SystemInformation_getProcessCPUTime
  (JNIEnv *env, jclass cls) {
    FILETIME creation, exit, kernel, user;
    GetProcessTimes(s_currentProcess, &creation, &exit, &kernel, &user);
    // 核心+用戶時間 除以 CPU 核心數 再換算為毫秒 (100ns 為單位)
    return (fileTimeToInt64(&kernel) + fileTimeToInt64(&user))
           / (s_numberOfProcessors * 10000);
}

fileTimeToInt64 將 FILETIME 轉 64 位整數。

步驟 3:Java 端載入庫與快照 API


static { System.loadLibrary("silib"); } // silib.dll

public static final class CPUUsageSnapshot {
    public final long time, cpuTime;
    private CPUUsageSnapshot(long t, long c) { time=t; cpuTime=c; }
}

public static CPUUsageSnapshot makeCPUUsageSnapshot() {
    return new CPUUsageSnapshot(System.currentTimeMillis(), getProcessCPUTime());
}

public static double getProcessCPUUsage(CPUUsageSnapshot start, CPUUsageSnapshot end) {
    return (double)(end.cpuTime - start.cpuTime) / (end.time - start.time);
}

步驟 4:背景監控執行緒 (Observer 模式)


class CPUUsageThread extends Thread {
    private final List listeners = new ArrayList<>();
    private long sleepTime = 500; // 0.5 秒

    public void run() {
        while (!isInterrupted()) {
            CPUUsageSnapshot snap = SystemInformation.makeCPUUsageSnapshot();
            notifyListeners(snap);
            try { sleep(sleepTime); } catch (InterruptedException e) { return; }
        }
    }
    // add/remove/notifyListeners 略
}

示例:CPUmon 主程式


public class CPUmon implements Listener {
    public static void main(String[] args) throws Exception {
        if (args.length == 0) throw new IllegalArgumentException("usage: CPUmon  [args...]");
        CPUUsageThread monitor = CPUUsageThread.getInstance();
        monitor.addListener(new CPUmon());
        monitor.start();
        Class app = Class.forName(args[0]);
        Method main = app.getMethod("main", String[].class);
        String[] appArgs = Arrays.copyOfRange(args, 1, args.length);
        main.invoke(null, (Object)appArgs);
    }
    public void cpuUsageUpdated(CPUUsageSnapshot snap) { /* 列印或記錄 */ }
}

執行:java -Djava.library.path=. -cp silib.jar;SwingSet2.jar CPUmon SwingSet2,即可即時輸出 CPU 使用率。

資源

本文來自 JavaWorld:原文連結

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