代碼片段
public interface NetSdk extends StdCallLibrary {
NetSdk INSTANCE = (NetSdk) Native.loadLibrary(
"netSdkDLL" + File.separator + "NetSdk", NetSdk.class);
}
除路徑錯誤外的常見原因
| 原因 | 現象 | 排查方法 |
| 依賴 DLL 缺失 | UnsatisfiedLinkError: Can't load library | Dependency Walker (depends.exe) 打開目標 DLL,紅色項即缺失依賴 |
| 位數不匹配 | 32位 JVM 加載 64位 DLL 或反過來 | 檢查 java -version 與 DLL 位數一致(JNA 5.0+ 支持自動選擇 platform 子目錄) |
| 調用約定錯誤 | 調用崩潰/參數亂碼 | C++ 默認 __cdecl,Windows API 多為 __stdcall;接口需繼承 StdCallLibrary 或 Library |
| 名稱修飾 | 找不到函數入口點 | C++ 導出需 extern "C";用 dumpbin /exports 查看實際導出名 |
| 運行時庫缺失 | 加載時崩潰 (MSVCRxxx.dll not found) | 安裝對應 VC++ Redistributable;或靜態鏈接 /MT |
JNA 專用排查技巧
1. 啟用詳細日誌
System.setProperty("jna.debug_load", "true");
System.setProperty("jna.debug_load.jna", "true");
// 控制台將輸出嘗試的路徑、加載過程
2. 使用 NativeLibrary 顯式加載
NativeLibrary lib = NativeLibrary.getInstance("NetSdk"); // 自動搜索 java.library.path
NetSdk sdk = lib.getInstance(NetSdk.class);
3. 設置搜索路徑
// 代碼中動態添加
System.setProperty("jna.library.path", "/path/to/dll/dir");
// 或啟動參數
// -Djna.library.path=/path/to/dll/dir
完整檢查清單
- ✅ DLL 路徑在
java.library.path 或 jna.library.path 中
- ✅ JVM 與 DLL 位數一致(64位 JVM 必須加載 64位 DLL)
- ✅ 所有依賴 DLL 在同目錄或系統 PATH 中(Dependency Walker 驗證)
- ✅ 導出函數名匹配(
extern "C" + __stdcall)
- ✅ 目標機安裝對應 VC++ Redist(與編譯 DLL 所用 VS 版本一致)
- ✅ 接口繼承正確的 Library 基類(
StdCallLibrary vs Library)
- ✅ JNA 版本 ≥ 5.0(更好的跨平台、自動位數選擇)
典型錯誤訊息對照
// 依賴缺失
java.lang.UnsatisfiedLinkError: Error looking up function 'XXX': The specified procedure could not be found
// 位數不匹配
java.lang.UnsatisfiedLinkError: Can't load IA 32-bit .dll on a AMD 64-bit platform
// 運行時庫缺失
java.lang.UnsatisfiedLinkError: Can't load library: The application has failed to start because its side-by-side configuration is incorrect