Java 語言特性不在闡述,請參考相關文檔,但Java爲追求統一(跨平臺)而犧牲性能(不支持對IPC的訪問),從而使Java訪問底層受到侷限。java
這幾天因一個項目須要java調用到dll, java調用dll網上也有不少,隻言片語,沒有劃分或系統地闡明。本人蔘考網絡上並結合實際作一些整理,貼出來分享給你們供參考。windows
(一) Java 調用dll網絡
1. 有什麼方式可調用dllapp
java調用dll 經常使用幾種方式:框架
1.JNI(JAVA對本地操做的一種方法就是JNI);要本身生存頭文件,較麻煩。也比較容易出錯。這裏就不在闡明使用,請參考相關文檔。
2.JNA(Java Native Access)框架是一個開源的Java框架,是SUN公司主導開發的,創建在經典的JNI的基礎之上的一個框架;須要用戶對所使用的DLL文件事先進行封裝,才能裝載。另外須要在一個java接口中描述目標DLL中的函數與結構,從而使JNA自動實現Java接口到native function的映射,較麻煩。
下載jna.jar: https://jna.dev.java.net/servlets/ProjectDocumentList?folderID=7408&expandFolder=7408&folderID=0ide
3.JNative 一個開源的組件,方便調用已有動態庫中的方法,支持CallBack 。下載地址:JNative_1.4RC2_src.zip : http://jaist.dl.sourceforge.net/sourceforge/jnative/JNative_1.4RC2_src.zip函數
JNative.jar : http://nchc.dl.sourceforge.net/sourceforge/jnative/JNative.jar性能
JNative相對於其它同類開源組件的優勢:spa
1.容易使用.net
2.對數據類型的處理作的出色
3.支持CallBack
2.Java調用動態庫注意事項:
1. 如何裝載dll文件,以及如何定位所要使用的方法;
2. 數據類型是如何對應的;
3.如何給使用的方法傳遞參數;
4. 如何獲取返回的值。
文件用途:
解壓JNative-1.4.zip 得到三個文件,分別是:JNativeCpp.dll,libJNativeCpp.so,JNative.jar
JNativeCpp.dll Windows下用的,拷貝到windows / system32目錄下;
libJNativeCpp.so Linux下的,拷貝到系統目錄下;
JNative.jar 這是一個擴展包,導入工程LIB中或將其拷貝到jdk/jre/lib/ext 下,系統會自動加載。
一些關鍵的類及方法
通常用到的方法
1.org.xvolks.jnative.Jnative
裝載dll文件,定位函數 JNative(),setParameter(),setRetVal(),getRetVal() etc.
2.org.xvolks.jnative.pointers.Pointer
替代本地函數中的的指針,須要先申請一塊內存空間,才能建立 Pointer(),dispose()
3.org.xvolks.jnative.pointers.memory.MemoryBlockFactory
申請一塊內存空間 createMemoryBlock()
4.org.xvolks.jnative.exceptions.NativeException
拋出裝載,定位等方面的異常
5.org.xvolks.jnative.Type
列舉和管理Jnative須要的不一樣的數據類型
(二) 如何使用
下面以一個我在項目中使用JNative來實現的一個小例子來說解:
java 調用dll (ReaderDriver.dll 其中有三個方法), 主要功能, a.鏈接讀寫器 ;b.巡卡(讀出卡序列號);c.關閉讀寫器。
環境:
1.將JNativeCpp.dll ,拷貝到windows / system32目錄下;
2.將JNative.jar導入工程中,新建一個調用類:
代碼以下:
package ecard.sys.javadll;
import org.xvolks.jnative.JNative;
import org.xvolks.jnative.Type;
import org.xvolks.jnative.exceptions.NativeException;
import org.xvolks.jnative.pointers.Pointer;
import org.xvolks.jnative.pointers.memory.MemoryBlockFactory;
/** * *功能描述:java調用dll動態庫<br> * *建立時間:2011-7-11 上午10:32:44 * *做者:chenab * *版本:V1.0 * *版本全部:XXXXXX有限公司 * **/ public class EcardReaderImpl { /** * 鏈接讀寫器 * @param port * @return * @throws NativeException * @throws IllegalAccessException */ public String ConnectionReader(int port) throws NativeException, IllegalAccessException{ JNative n = null; try{ //1.建立JNative對象 n = new JNative("ReaderDriver.dll","ConnectReader"); //2.設置函數返回值類型 n.setRetVal(Type.INT); //3.設置參數類型 int i=0; n.setParameter(i++, port); //4.執行函數 n.invoke(); //5.獲取函數返回值 return n.getRetVal(); }finally{ if(n!=null){ n.dispose(); } } } /** * 巡卡 * @return * @throws NativeException * @throws IllegalAccessException */ public String ReqCardExist() throws NativeException, IllegalAccessException{ JNative n = null; try{ //1.建立JNative對象 n = new JNative("ReaderDriver.dll","RequestCardExist"); //2.設置函數返回值類型 n.setRetVal(Type.INT); //3.設置參數類型 //聲明指定內存空間 Pointer aa = new Pointer(MemoryBlockFactory.createMemoryBlock(100)); Pointer bb = new Pointer(MemoryBlockFactory.createMemoryBlock(100)); n.setParameter(0,aa); n.setParameter(0,bb); //4.執行函數 n.invoke(); StringBuffer sb = new StringBuffer(); String type = Integer.toHexString(getResult(aa.getAsByte(0))); if("8".equals(type)){ sb.append(Integer.toHexString(getResult(aa.getAsByte(0)))); sb.append(Integer.toHexString(getResult(aa.getAsByte(1)))); sb.append(Integer.toHexString(getResult(aa.getAsByte(2)))); sb.append(Integer.toHexString(getResult(aa.getAsByte(3)))); }else{ sb.append(Integer.toHexString(getResult(aa.getAsByte(0)))); sb.append(Integer.toHexString(getResult(aa.getAsByte(1)))); sb.append(Integer.toHexString(getResult(aa.getAsByte(2)))); sb.append(Integer.toHexString(getResult(aa.getAsByte(3)))); sb.append(Integer.toHexString(getResult(aa.getAsByte(4)))); sb.append(Integer.toHexString(getResult(aa.getAsByte(5)))); sb.append(Integer.toHexString(getResult(aa.getAsByte(6)))); sb.append(Integer.toHexString(getResult(aa.getAsByte(7)))); } //5.獲取函數返回值 return sb.toString(); }finally{ if(n!=null){ n.dispose(); } } } /** * 反碼,高低位轉換 * @param a * @return */ private int getResult(int a){ if(a<0){ a=a+256; } return a; } /** * 讀卡器蜂鳴 * @return * @throws NativeException * @throws IllegalAccessException */ public String CardVoice() throws NativeException, IllegalAccessException{ JNative n = null; try{ //1.建立JNative對象 n = new JNative("ReaderDriver.dll","CardBeep"); //設置函數返回值類型 n.setRetVal(Type.INT); //設置參數類型 //執行函數 n.invoke(); //獲取函數返回值 return n.getRetVal(); }finally{ if(n!=null){ n.dispose(); } } } /** * 關閉讀卡器 * @return * @throws NativeException * @throws IllegalAccessException */ public String CloseReader() throws NativeException, IllegalAccessException{ JNative n = null; try{ //1.建立JNative對象 n = new JNative("ReaderDriver.dll","CloseReader"); //設置函數返回值類型 n.setRetVal(Type.INT); //設置參數類型 //執行函數 n.invoke(); //獲取函數返回值 return n.getRetVal(); }finally{ if(n!=null){ n.dispose(); } } } public static void main(String[] args)throws NativeException, IllegalAccessException { EcardReaderImpl impl = new EcardReaderImpl(); System.out.println("鏈接讀卡器=="+impl.ConnectionReader(1)); System.out.println("蜂鳴=="+impl.ReqCardExist()); System.out.println("巡卡=="+impl.CardVoice()); System.out.println("關閉讀寫器=="+impl.CloseReader()); } }