前言
Java 標準庫對作業系統底層資訊(CPU、記憶體、磁碟、網路)支援有限。Hyperic Sigar 是一個成熟的跨平台系統資訊庫,透過 JNI 呼叫原生 API,提供統一介面獲取硬體與 OS 指標。本文整理完整實作範例,涵蓋 CPU、記憶體、檔案系統、網路介面、作業系統資訊等核心場景。
環境準備
- 下載
sigar.jar 並加入專案類路徑。
- 根據部署環境放置原生庫:
- Windows x64:
sigar-amd64-winnt.dll
- Windows x86:
sigar-x86-winnt.dll
- Linux x64:
libsigar-amd64-linux.so
- Linux x86:
libsigar-x86-linux.so
原生庫需放在 java.library.path 指定目錄或系統 PATH 中。
核心工具類:SysInfo
import org.hyperic.sigar.*;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class SysInfo {
private static final Sigar sigar = new Sigar();
// ========== CPU 資訊 ==========
public static int getCpuCount() throws SigarException {
return sigar.getCpuInfoList().length;
}
public static void printCpuDetails() throws SigarException {
CpuInfo[] infos = sigar.getCpuInfoList();
for (int i = 0; i < infos.length; i++) {
CpuInfo info = infos[i];
System.out.printf("CPU[%d]: MHz=%d, Vendor=%s, Model=%s, Cache=%d KB%n",
i, info.getMhz(), info.getVendor(), info.getModel(), info.getCacheSize());
}
}
public static void printCpuUsage() throws SigarException {
CpuPerc[] cpuList = sigar.getCpuPercList();
for (int i = 0; i < cpuList.length; i++) {
CpuPerc cpu = cpuList[i];
System.out.printf("CPU[%d] User=%.1f%% Sys=%.1f%% Idle=%.1f%% Total=%.1f%%%n",
i,
cpu.getUser() * 100, cpu.getSys() * 100,
cpu.getIdle() * 100, cpu.getCombined() * 100);
}
}
// ========== 記憶體資訊 ==========
public static void printMemoryInfo() throws SigarException {
Mem mem = sigar.getMem();
Swap swap = sigar.getSwap();
System.out.println("=== 物理記憶體 ===");
System.out.printf("Total: %,d MB%n", mem.getTotal() / 1024 / 1024);
System.out.printf("Used: %,d MB%n", mem.getUsed() / 1024 / 1024);
System.out.printf("Free: %,d MB%n", mem.getFree() / 1024 / 1024);
System.out.println("=== Swap 交換區 ===");
System.out.printf("Total: %,d MB%n", swap.getTotal() / 1024 / 1024);
System.out.printf("Used: %,d MB%n", swap.getUsed() / 1024 / 1024);
System.out.printf("Free: %,d MB%n", swap.getFree() / 1024 / 1024);
}
// ========== 作業系統資訊 ==========
public static String getHostName() {
try {
return InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
try { return sigar.getNetInfo().getHostName(); }
catch (SigarException ignored) { return "localhost.unknown"; }
}
}
public static void printOsInfo() {
OperatingSystem os = OperatingSystem.getInstance();
System.out.println("Arch: " + os.getArch());
System.out.println("Description: " + os.getDescription());
System.out.println("Name: " + os.getName());
System.out.println("Version: " + os.getVersion());
System.out.println("Vendor: " + os.getVendor());
}
// ========== 檔案系統(磁碟) ==========
public static void printFileSystemInfo() throws SigarException {
FileSystem[] fsList = sigar.getFileSystemList();
for (int i = 0; i < fsList.length; i++) {
FileSystem fs = fsList[i];
FileSystemUsage usage = sigar.getFileSystemUsage(fs.getDirName());
System.out.printf("%n=== Partition %d: %s (%s) ===%n",
i, fs.getDevName(), fs.getDirName());
System.out.printf("Type: %s | SysType: %s | Flags: %s%n",
fs.getTypeName(), fs.getSysTypeName(), fs.getFlags());
if (fs.getType() == FileSystem.TYPE_LOCAL_DISK) {
System.out.printf("Total: %,d GB | Free: %,d GB | Used: %,d GB | Usage: %.1f%%%n",
usage.getTotal() / 1024 / 1024 / 1024,
usage.getFree() / 1024 / 1024 / 1024,
usage.getUsed() / 1024 / 1024 / 1024,
usage.getUsePercent() * 100);
System.out.printf("Reads: %,d | Writes: %,d%n",
usage.getDiskReads(), usage.getDiskWrites());
}
}
}
// ========== 網路資訊 ==========
public static String getDefaultIp() {
try {
String ip = InetAddress.getLocalHost().getHostAddress();
if (!NetFlags.LOOPBACK_ADDRESS.equals(ip)) return ip;
} catch (UnknownHostException ignored) {}
try { return sigar.getNetInterfaceConfig().getAddress(); }
catch (SigarException e) { return NetFlags.LOOPBACK_ADDRESS; }
}
public static String getMacAddress() {
try {
String[] ifaces = sigar.getNetInterfaceList();
for (String iface : ifaces) {
NetInterfaceConfig cfg = sigar.getNetInterfaceConfig(iface);
if (NetFlags.LOOPBACK_ADDRESS.equals(cfg.getAddress()) ||
(cfg.getFlags() & NetFlags.IFF_LOOPBACK) != 0 ||
NetFlags.NULL_HWADDR.equals(cfg.getHwaddr())) {
continue;
}
return cfg.getHwaddr();
}
} catch (SigarException ignored) {}
return null;
}
public static void printNetworkStats() throws SigarException {
String[] ifNames = sigar.getNetInterfaceList();
for (String name : ifNames) {
NetInterfaceConfig cfg = sigar.getNetInterfaceConfig(name);
if ((cfg.getFlags() & 1L) == 0) continue; // IFF_UP
NetInterfaceStat stat = sigar.getNetInterfaceStat(name);
System.out.printf("%nInterface: %s (%s)%n", name, cfg.getAddress());
System.out.printf(" RX: %,d packets, %,d bytes, %,d errors, %,d dropped%n",
stat.getRxPackets(), stat.getRxBytes(), stat.getRxErrors(), stat.getRxDropped());
System.out.printf(" TX: %,d packets, %,d bytes, %,d errors, %,d dropped%n",
stat.getTxPackets(), stat.getTxBytes(), stat.getTxErrors(), stat.getTxDropped());
}
}
// ========== 登入用戶 ==========
public static void printLoggedInUsers() throws SigarException {
Who[] users = sigar.getWhoList();
for (int i = 0; i < users.length; i++) {
Who u = users[i];
System.out.printf("User[%d]: %s @ %s on %s since %d%n",
i, u.getUser(), u.getHost(), u.getDevice(), u.getTime());
}
}
public static void main(String[] args) {
try {
printCpuDetails();
printCpuUsage();
printMemoryInfo();
printOsInfo();
printFileSystemInfo();
System.out.println("Host: " + getHostName());
System.out.println("IP: " + getDefaultIp());
System.out.println("MAC: " + getMacAddress());
printNetworkStats();
printLoggedInUsers();
} catch (Exception e) {
e.printStackTrace();
} finally {
try { sigar.close(); } catch (Exception ignored) {}
}
}
}
關鍵類別與方法對照表
| 功能 | Sigar 類別 | 核心方法 |
| CPU 邏輯核心數 | CpuInfo | getCpuInfoList().length |
| CPU 使用率 | CpuPerc | getCpuPercList() → getUser()/getSys()/getIdle()/getCombined() |
| 物理記憶體 | Mem | getMem() → getTotal()/getUsed()/getFree() |
| Swap 交換區 | Swap | getSwap() → getTotal()/getUsed()/getFree() |
| 檔案系統列表 | FileSystem | getFileSystemList() |
| 分區使用率 | FileSystemUsage | getFileSystemUsage(dir) → getTotal()/getFree()/getUsePercent() |
| 網路介面配置 | NetInterfaceConfig | getNetInterfaceConfig(name) → getAddress()/getNetmask()/getHwaddr() |
| 網路流量統計 | NetInterfaceStat | getNetInterfaceStat(name) → getRxBytes()/getTxBytes()/getRxPackets()/getTxPackets() |
| 登入用戶 | Who | getWhoList() → getUser()/getHost()/getTime() |
常見問題與解決方案
- UnsatisfiedLinkError:原生庫未找到。確認
sigar-amd64-winnt.dll 或 .so 檔案在 java.library.path 或系統 PATH 中。
- 權限不足:Linux 下讀取
/proc 或網路統計可能需要 root 權限。
- 資源洩漏:
Sigar 實例實作 AutoCloseable,使用後務必呼叫 close() 釋放原生資源。
- 多網卡 MAC 選擇:範例回傳第一張非回環、非虛擬介面的 MAC;實際部署可根據介面名稱或 IP 段過濾。
替代方案對比