使用JNI你得完成上面這些步驟,比較麻煩,而是用JNA就省事多了,基本上不需要脫離Java環(huán)境就可以完成。
JNA項目主頁是https://jna.dev.java.net/, 目前最新的版本是3.2.4 。下載時記得將自帶的Example.jar 也下載下來,這個里面提供了一些JNA的例子,通過這個能夠更快的了解JNA。
使用JNA的調用本地方法的時候需要自定義數(shù)據(jù)結構,下面我們通過調用Windows提供的的鎖定工作站方法來了解一下JNA。
1、首先查詢Windows API知道鎖定工作站的方法在user32.dll中定義,接下來定義一個接口來繼承JNA的Library.java接口,用作聲明DLL庫文件,這里我們就把它命名為User32:

2、查詢user32.dll提供的API得知鎖定工作方法是LockWorkStation,返回類型是boolean型,在User32.java中新增相應的方法:
這樣我們的User32.java這個類就定義好了。接下來我們寫測試程序進行調用。
3、編寫測試類比如LockWorkStation.java,首先通過JNA的Native類加載對應的dll:
然后就可以調用LockWorkStation方法了,完整代碼如下:
public static void main(String[] args) {
User32 user32 = (User32) Native.loadLibrary("user32", User32.class);
user32.LockWorkStation();
}
}
這里說明一下loadLibrary方法中第一個參數(shù)是需要加載的dll文件名稱,第二個參數(shù)的作用是讓JNA使用這個類的加載器去加載DLL文件,加載順序是,先從Users.class類的當前文件夾找,如果沒有找到,再在工程當前文件夾下面找win32/win64文件夾,找到后搜索對應的dll文件,如果找不到再到WINDOWS下面去搜索,再找不到就會拋異常了。以TWAINDSM.dll將文件放到工程的根文件夾可以按照下面這個格式放:
private boolean immutable;
public HANDLE() { }
public HANDLE(Pointer p) { setPointer(p); immutable = true; }
public Object fromNative(Object nativeValue, FromNativeContext context) {
Object o = super.fromNative(nativeValue, context);
if (INVALID_HANDLE_VALUE.equals(o))
return INVALID_HANDLE_VALUE;
return o;
}
public void setPointer(Pointer p) {
if (immutable)
throw new UnsupportedOperationException("immutable reference");
super.setPointer(p);
}
}
public int x, y;
public POINT() { }
public POINT(int x, int y) { this.x = x; this.y = y; }
}
使用JNA的過程中也不一定會一帆風順,比如會拋出”非法內存訪問”,這時候檢查一下變量是否==null。還有內存對齊的問題,當從內存中獲取圖片信息進行保存的時候,如果內存對齊處理不好,就會拋出很嚴重的異常,導致JVM異常退出,JNA提供了四種內存對齊的方式,分別是:ALIGN_DEFAULT、ALIGN_NONE、ALIGN_GNUC和ALIGN_MSVC。ALIGN_DEFAULT采用平臺默認的對齊方式(推薦);ALIGN_NONE是不采用對齊方式;ALIGN_GNUC為針對linux/gcc操作系統(tǒng)的對齊方式。ALIGN_MSVC為針對win32/msvc架構的內存對齊方式。
JNA也提供了一種保護機制.比如防止JNA出現(xiàn)異常不會導致JVM異常退出,默認是開啟這個功能的,開啟方式為System.setProperty(“jna.protected”,”true”); 記得要在JNA加載dll文件之前調用,然后try {...} catch(Throwable e)異常,不過你也不要期望過高,不要以為加上這個就萬事大吉,出現(xiàn)”非法內存訪問”的時候還是會束手無策。JNA也提供了一種保護機制.比如防止JNA出現(xiàn)異常不會導致JVM異常退出,默認是開啟這個功能的,開啟方式為System.setProperty(“jna.protected”,”true”); 記得要在JNA加載dll文件之前調用,然后try {...} catch(Throwable e)異常,不過你也不要期望過高,不要以為加上這個就萬事大吉,出現(xiàn)”非法內存訪問”的時候還是會束手無策。