java呼叫dll的幾種方法
前些天做單點登入,需要java呼叫dll,現在把成功經驗與大家分享。
使用Java呼叫DLL動態連結庫的方案通常有三種:JNI, Jawin, Jacob. 其中JNI(Java Native
Interface)是Java語言本身提供的呼叫本地已編譯的函式庫的方法,本身具有跨平臺性,可以在不同的
機器上呼叫不同的本地庫。Jawin和Jacob都是sourceforge.net的開源專案,都是基於JNI技術的依賴Wi
ndows的實現,使得在Windows平臺下使用COM和DLL的更加方便。
一、JNI(Java本地方法呼叫)
JNI的應用方案是基於Java類和本地函式相對映的。其使用DLL的步驟還是相對比較麻煩,不但涉及
到Java程式設計,還涉及到C/C++程式設計。
JNI的使用步驟是:
1. 編寫Java類,用該類將DLL對外提供的函式服務進行宣告,其中的Java方法均宣告為native,其方法
簽名可以自定義,不用實現函式體。
2. 用Javah工具將該Java類生成對應的.h標頭檔案。
3.
最重要的比較麻煩的一步:編寫C/C++程式碼實現.h標頭檔案中宣告的函式,該C/C++程式碼中包含jni.h頭文
件,並且編寫程式碼時使用其中定義好的資料型別作為函式的輸入和返回資料型別進行程式設計。用這種方法
實現資料型別轉換。在該步驟中,可以在C/C++程式碼中呼叫已經存在的DLL庫(當別人給我們提供一個現
成的dll控制元件時,我們只知道介面,不能改變它的實現,就需要“自定義的dll”呼叫“現成dll”)
4. 另外編寫的Java程式碼時就可以使用該Java類了。
在第3步中,編寫C/C++函式時,可以使用一個叫interface pointer的env指標來呼叫JNI提供的一系列(
很多)函式,用這些函式來訪問JVM的物件和資料。
使用JNI的缺點:使用比較麻煩,需要對已有的DLL進行封裝,需要對C/C++比較瞭解。
使用JNI的優點:可以跨平臺呼叫本地庫。
二、Jawin
Jawin的應用方案是基於函式呼叫時採用原始位元組流傳遞資料的。就是在Java中指明一個DLL中的某個函
數後,通過原始位元組流(需要考慮引數資料型別所佔的儲存位元組數及系統使用的位元組序列)傳遞給該DLL
函式需要的引數,其返回值也是通過原始位元組流解析的方式獲得正確的值。
Jawin有一個Jawin.dll和Jawin.jar,根據開發環境不同,需要不同的配置.
使用Jawin的缺點:不方便除錯,幾乎所有的錯誤都丟擲同樣的異常COMException;需要對資料型別的
轉換比較瞭解;不能跨平臺,對Windows的依賴性比較強。
使用Jawin的優點:方便使用,不用進行C/C++開發,不用對原始DLL進行封裝就可以方便使用。
本人體會:我在用 Jawin 呼叫單點的dll時,多次出現錯誤,最終除錯失敗,後來檢視它的官方文件,
發現它對某些com呼叫不支援。
三、Jacob
Jacob是Java-Com Bridge的縮寫,也可以用來呼叫DLL。其底層也是使用JNI實現,也具有Windows 的平
臺依賴性。
該控制元件呼叫相當方便,可以呼叫com和active, 幾分鐘就可以搞定,它下載後有一個dll和一個jar包,
把dll放到WIN_HOME/system32/下既可,把jar包放到工程的classpath下。
下面是我呼叫單點dll的事例:
import com.jacob.com.*;
public class CallSSO {
private static Dispatch dif;
//載入單點控制元件SSOCrypto.SSOCrypt.1
static {
dif = new Dispatch("SSOCrypto.SSOCrypt.1");
}
//產生隨機碼,呼叫單點的介面SSORadomGen,傳遞引數是strPlainString
public static int SSORadomGen(String strPlainString)
{
Variant radom = Dispatch.call(dif, "SSORadomGen", new Variant(strPlainString));
return radom.getInt();
}
//取的加密串,呼叫單點的介面SSOEncrypt,傳遞引數是strPlainString,lngRandomnum,strSvrCert
public static String SSOEncrypt(String strPlainString,
int lngRandomnum)
{
String strSvrCert ="1BQYR-YLGXV-QM439-CJSCS-TCN6V";
Variant encrypt = Dispatch.call(dif, "SSOEncrypt", new
Variant(strPlainString),new Variant(lngRandomnum),new Variant(strSvrCert));
return encrypt.getString();
}
}
缺點:不能跨平臺,對Windows的依賴性比較強。
優點:呼叫相當方便,不用進行C/C++開發,不用對原始DLL進行封裝就可以方便使用。