純 Java 無直接 API 獲取 CPU 使用率。常見替代方案:Runtime.exec() 呼叫 ps 解析 PID,但跨平台、效能、權限皆有問題。更可靠方案:JNI 呼叫原生 C 代碼 (Windows 示例)。
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);
#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 位整數。
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);
}
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 略
}
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:原文連結