給大家介紹一個(gè)最新的訪問(wèn)本機(jī)代碼的 Java 框架 —JNA 。
JNA(Java Native Access) 框架是一個(gè)開(kāi)源的 Java 框架,是 SUN 公司主導(dǎo)開(kāi)發(fā)的,建立在經(jīng)典的 JNI 的基礎(chǔ)之上的一個(gè)框架。
JNA 項(xiàng)目地址: https://jna.dev.java.net/
非常強(qiáng)大、易用,功能上類(lèi)似與 .NET 的 P/Invoke 。
不堪回首的 JNI我們知道,使用 JNI 調(diào)用 .dll/.so 共享類(lèi)庫(kù)是非常非常麻煩和痛苦的。
如果有一個(gè)現(xiàn)有的 .dll/.so 文件,如果使用 JNI 技術(shù)調(diào)用,我們首先需要另外使用 C 語(yǔ)言寫(xiě)一個(gè) .dll/.so 共享庫(kù),使用 SUN 規(guī)定的數(shù)據(jù)結(jié)構(gòu)替代 C 語(yǔ)言的數(shù)據(jù)結(jié)構(gòu),調(diào)用已有的 dll/so 中公布的函數(shù)。
然后再在 Java 中載入這個(gè)適配器 dll/so ,再編寫(xiě) Java native 函數(shù)作為 dll 中函數(shù)的代理。
經(jīng)過(guò) 2 個(gè)繁瑣的步驟才能在 Java 中調(diào)用本地代碼。
因此,很少有 Java 程序員愿意編寫(xiě)調(diào)用 dll/.so 庫(kù)中的原生函數(shù)的 java 程序。這也使 Java 語(yǔ)言在客戶端上乏善可陳?梢哉f(shuō) JNI 是 Java 的一大弱點(diǎn)!
.NET 平臺(tái)上強(qiáng)大的 P/Invoke
而在 .NET 平臺(tái)上,強(qiáng)大的 P/Invoke 技術(shù)使我們 Java 程序員非常羨慕。使用 P/Invoke 技術(shù),只需要使用編寫(xiě)一個(gè) .NET 函數(shù),再加上一個(gè)聲明的標(biāo)注,就可以直接調(diào)用 dll 中的函數(shù)。
不需要你再使用 C 語(yǔ)言編寫(xiě) dll 來(lái)適配。
不遜于 P/Invoke 的 JNA
現(xiàn)在,不需要再羨慕 .NET 的 P/Invoke 機(jī)制了。 JNA 把對(duì) dll/.so 共享庫(kù)的調(diào)用減少到了和 P/Invoke 相同的程度。
使用 JNA ,不需要再編寫(xiě)適配用的 .dll/.so ,只需要在 Java 中編寫(xiě)一個(gè)接口和一些代碼,作為 .dll/.so 的代理,就可以在 Java 程序中調(diào)用 dll/so 。
JNA 快速啟動(dòng)
現(xiàn)在讓我們直接進(jìn)入 JNA 的世界。
你只需要下載一個(gè) jar 包,就可以使用 JNA 的強(qiáng)大功能方便地調(diào)用動(dòng)態(tài)鏈接庫(kù)中的 C 函數(shù)。
1 ,下載 jna.jar 。
在這里 https://jna.dev.java.net/servlets/ProjectDocumentList?folderID=7408&expandFolder=7408&folderID=0
2 ,現(xiàn)在你已經(jīng)可以使用 JNA 了。
為了方便你參考 JNA 的 java 類(lèi)庫(kù),我制作了《 JNA3.09API 參考手冊(cè)》,是 CHM 格式的。你可以到這里下載 http://download.csdn.net/source/900438
JNA 例子
例子 1
現(xiàn)在讓我們運(yùn)行一個(gè) JNA 程序,感受它的強(qiáng)大威力。
1 ,在 Java 項(xiàng)目中引入 jna.jar 包。
2 ,創(chuàng)建一個(gè)類(lèi):
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
/** Simple example of native library declaration and usage. */
public class HelloWorld {
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary)
Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"),
CLibrary.class);
void printf(String format, Object... args);
}
public static void main(String[] args) {
CLibrary.INSTANCE.printf("Hello, World\n");
for (int i=0;i < args.length;i++) {
CLibrary.INSTANCE.printf("Argument %d: %s\n", i, args[i]);
}
}
}
3 ,執(zhí)行,可以看到控制臺(tái)中打印出了
Hello, World
但是,請(qǐng)注意,這個(gè)程序?qū)嶋H上是使用 msvcrt.dll 這個(gè) C 運(yùn)行時(shí)庫(kù)中的 printf 函數(shù)打印出上面這些字符的。
看,多簡(jiǎn)單,不需要寫(xiě)一行 C 代碼,就可以直接在 Java 中調(diào)用外部動(dòng)態(tài)鏈接庫(kù)中的函數(shù)!
例子 2
上面那個(gè)例子使用了操作系統(tǒng)自帶的動(dòng)態(tài)鏈接庫(kù),現(xiàn)在我們?cè)僮约簩?xiě)一個(gè)動(dòng)態(tài)鏈接庫(kù)試試。
1 ,在 VS 中選擇 C++ 語(yǔ)言,然后選擇創(chuàng)建一個(gè) Win32 程序。 選擇 dll 類(lèi)型。
2 ,發(fā)布的 C 函數(shù)是:
#define MYLIBAPI extern "C" __declspec ( dllexport )
MYLIBAPI void say( wchar_t * pValue);
這個(gè)函數(shù)的實(shí)現(xiàn)是:
void say( wchar_t * pValue){
std::wcout.imbue(std::locale( "chs" ));
std::wcout<<L "上帝說(shuō):" <<pValue<<std::endl;
}
它需要傳入一個(gè) Unicode 編碼的字符數(shù)組。然后在控制臺(tái)上打印出一段中文字符。
3 ,生成 dll 。然后把生成的 dll 文件復(fù)制到 Eclipse 項(xiàng)目中,放在項(xiàng)目下面。
4 ,在 Eclipse 中編寫(xiě)以下代碼:
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.WString;
/**
* @author 沈東良 Edward Shen shendl_s@hotmail.com
* 2008-11-23 下午 05:07:14
*TestDll1.dll
*/
public class TestDll1Service {
public interface TestDll1 extends Library {
/**
* 當(dāng)前路徑是在項(xiàng)目下,而不是 bin 輸出目錄下。
*/
TestDll1 INSTANCE = (TestDll1)Native.loadLibrary("TestDll1", TestDll1.class);
public void say(WString value);
}
/**
*
*/
public TestDll1Service() {
// TODO Auto-generated constructor stub
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
TestDll1.INSTANCE.say(new WString("Hello World!"));
System.out.println("HHEEH 我我們無(wú)法萬(wàn)惡 ");
}
}
5 ,執(zhí)行這個(gè) Java 類(lèi)?梢钥吹娇刂婆_(tái)下如下輸出:
上帝說(shuō): Hello World!
HHEEH 我我們無(wú)法萬(wàn)惡
6 ,上面一行是 C 語(yǔ)言使用 C++ 的 std::wcout 輸出的。
下面一行是 Java 語(yǔ)言輸出的。
JNA 技術(shù)解密 JNA 工作原理
JNA 是建立在 JNI 技術(shù)基礎(chǔ)之上的一個(gè) Java 類(lèi)庫(kù),它使您可以方便地使用 java 直接訪問(wèn)動(dòng)態(tài)鏈接庫(kù)中的函數(shù)。
原來(lái)使用 JNI ,你必須手工用 C 寫(xiě)一個(gè)動(dòng)態(tài)鏈接庫(kù),在 C 語(yǔ)言中映射 Java 的數(shù)據(jù)類(lèi)型。
JNA 中,它提供了一個(gè)動(dòng)態(tài)的 C 語(yǔ)言編寫(xiě)的轉(zhuǎn)發(fā)器,可以自動(dòng)實(shí)現(xiàn) Java 和 C 的數(shù)據(jù)類(lèi)型映射。你不再需要編寫(xiě) C 動(dòng)態(tài)鏈接庫(kù)。
當(dāng)然,這也意味著,使用 JNA 技術(shù)比使用 JNI 技術(shù)調(diào)用動(dòng)態(tài)鏈接庫(kù)會(huì)有些微的性能損失?赡芩俣葧(huì)降低幾倍。但影響不大。
JNA 技術(shù)難點(diǎn)
1 ,當(dāng)前路徑是在項(xiàng)目下,而不是 bin 輸出目錄下。
2 ,數(shù)據(jù)結(jié)構(gòu)的對(duì)應(yīng)關(guān)系:
Java—C 和操作系統(tǒng)數(shù)據(jù)類(lèi)型的對(duì)應(yīng)表
Java Type |
C Type |
Native Representation |
boolean |
int |
32-bit integer (customizable) |
byte |
char |
8-bit integer |
char |
wchar_t |
platform-dependent |
short |
short |
16-bit integer |
int |
int |
32-bit integer |
long |
long long, __int64 |
64-bit integer |
float |
float |
32-bit floating point |
double |
double |
64-bit floating point |
pointer |
platform-dependent (32- or 64-bit pointer to memory) |
|
<T>[] (array of primitive type) |
pointer |
32- or 64-bit pointer to memory (argument/return) |
除了上面的類(lèi)型, JNA 還支持常見(jiàn)的數(shù)據(jù)類(lèi)型的映射。 |
||
char* |
NUL-terminated array (native encoding or jna.encoding ) |
|
wchar_t* |
NUL-terminated array (unicode) |
|
char** |
NULL-terminated array of C strings |
|
wchar_t** |
NULL-terminated array of wide C strings |
|
struct* |
pointer to struct (argument or return) (
or explicitly
) |
|
union |
same as Structure |
|
struct[] |
array of structs, contiguous in memory |
|
<T> (*fp)() |
function pointer (Java or native) |
|
varies |
depends on definition |
|
long |
platform-dependent (32- or 64-bit integer) |
|
pointer |
same as Pointer |
轉(zhuǎn)載:
http://blog.csdn.net/shendl/archive/2008/12/23/3589676.aspx
JNA—JNI終結(jié)者.rar (89.1 KB)歡迎光臨 Chinaunix (http://www.72891.cn/) | Powered by Discuz! X3.2 |