Java Native Access (JNA) 讓 Java 直接呼叫原生函式庫(DLL/.so),無需撰寫 JNI 胶水代碼、編譯 Header、處理複雜的類型映射。它避免了修改遺留 C/C++ 代碼、昂貴的專有橋接方案,並有效取代傳統 JNI。
定義介面繼承 Library,宣告需呼叫的原生函式:
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary(
Platform.isWindows() ? "kernel32" : "c", CLibrary.class);
int GetTickCount(); // 系統啟動至今毫秒數
}
public static void main(String[] args) {
System.out.println("TickCount: " + CLibrary.INSTANCE.GetTickCount());
}
無需 JNI,直接對應 DLL 符號即可呼叫。
JNA 可直接映射 C 結構體:
Kernel32 lib = Kernel32.INSTANCE;
SYSTEMTIME time = new SYSTEMTIME();
lib.GetSystemTime(time);
System.out.println("Day: " + time.wDay);
Java 程式碼取得低層平台資料,展現 JNA 橋接能力。
關鍵代碼:
extern "C" __declspec(dllexport) DWORD helloWorld(DWORD divider) {
return 77 / divider;
}
需設定呼叫慣例為 __cdecl,編譯產出 nativecode.dll。
public interface NativeLib extends Library {
NativeLib INSTANCE = (NativeLib) Native.loadLibrary("nativecode", NativeLib.class);
int helloWorld(int divider);
}
測試呼叫與例外處理(除零錯誤)展示 JNA 靈活性。
JNA 以純 Java 方式實現高效原生互操作,大幅降低整合遺留代碼的門檻與維護成本。下篇將深入進階用法。