Sigar (System Information Gatherer And Reporter) 是一個強大的跨平台系統信息收集庫,通過 JNI 調用底層 C 實現,可獲取 CPU、內存、磁盤、網絡、進程等豐富指標。但初次使用時常遇到 UnsatisfiedLinkError,本文提供極速排查與解決方案。
Exception in thread "main" java.lang.UnsatisfiedLinkError:
no sigar-x86-winnt.dll in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867)
at org.hyperic.sigar.Sigar.loadLibrary(Sigar.java:172)
...
原因: Java 找不到平台相關的動態鏈接庫(Windows 下為 sigar-x86-winnt.dll,Linux 為 libsigar-amd64-linux.so 等)。
官網:https://sigar.hyperic.com/ → 下載 hyperic-sigar-1.6.4.zip(或最新版)。解壓後目錄結構:
sigar-bin/
lib/
sigar.jar ← Java API
log4j-1.2.15.jar ← 依賴
lib/
sigar-x86-winnt.dll ← Windows 32 位
sigar-amd64-winnt.dll ← Windows 64 位
libsigar-x86-linux.so ← Linux 32 位
libsigar-amd64-linux.so ← Linux 64 位
... (其他平台)
sigar.jar、log4j.jar 加入 Classpath (Maven/Gradle 或手動導入 lib 目錄)。方案 A(最簡單,開發/測試適用): 將對應平台的動態庫複製到 JDK 安裝目錄的 bin 目錄下(如 C:\Program Files\Java\jdk1.8.0_XXX\bin\)。
sigar-amd64-winnt.dll(或舊版中的 sigar-x86-winnt.dll,視 Sigar 版本而定)。java.library.path 默認包含 JDK bin 目錄。方案 B(生產/容器化推薦): 啟動參數指定 -Djava.library.path=/path/to/native/lib。
java -Djava.library.path=/opt/sigar/lib -cp app.jar:lib/sigar.jar:lib/log4j.jar com.example.Main
ENV JAVA_OPTS="-Djava.library.path=/usr/local/sigar/lib"。.so/.dll 放入映像的 /usr/local/sigar/lib。方案 C(Web 容器/應用服務器): 將動態庫放入容器的共享庫路徑(如 Tomcat 的 bin 目錄、或系統 /usr/lib),並確保運行用戶有讀取/執行權限。
import org.hyperic.sigar.Sigar;
import org.hyperic.sigar.CpuPerc;
public class SigarTest {
public static void main(String[] args) throws Exception {
Sigar sigar = new Sigar();
CpuPerc cpu = sigar.getCpuPerc();
System.out.println("CPU 用戶態: " + cpu.getUser());
System.out.println("CPU 系統態: " + cpu.getSys());
System.out.println("CPU 空閒: " + cpu.getIdle());
// 更多指標參考 Sigar API 文檔
}
}
| 坑點 | 現象 | 解決 |
|---|---|---|
| 32/64 位不匹配 | UnsatisfiedLinkError: Can't load IA 32-bit .dll on a AMD 64-bit platform | JDK 與動態庫位數必須一致:64 位 JDK 用 amd64 庫,32 位 JDK 用 x86 庫 |
| 多版本衝突 | 類路徑有多個 sigar.jar | 清理依賴,保留單一版本 |
| Linux 缺少依賴庫 | 載入 .so 失敗,提示缺少 libc 等 | 安裝 glibc、libstdc++ 等基礎庫;Alpine Linux 需安裝 libc6-compat |
| 權限不足 | 無法讀取 /proc 或動態庫 | 確保運行用戶有權限;容器需以 root 或特權運行 |
若不想處理 JNI 載入問題,推薦 oshi:
<dependency><groupId>com.github.oshi</groupId><artifactId>oshi-core</artifactId><version>6.4.0</version></dependency>SystemInfo si = new SystemInfo(); CentralProcessor cpu = si.getHardware().getProcessor();Sigar 功能強大但受限於 JNI 載入機制。開發期直接把 dll/so 扔進 JDK bin 目錄最省事;生產期務必用 -Djava.library.path 顯式指定路徑。若追求零運維成本,oshi 是更現代的選擇。