JNA

JNA(Java Native Access)是建立在JNI(Java Native Interface,Java本地調(diào)用)技術(shù)之上的Java開(kāi)源框架嗜暴,JNA提供了一組Java工具類用于在運(yùn)行期間動(dòng)態(tài)訪問(wèn)系統(tǒng)本地庫(kù)(Native Library精堕,如Windows的動(dòng)態(tài)鏈接庫(kù)*.dll孵淘、Linux的共享庫(kù)*.so)。

使用JNA開(kāi)發(fā)后無(wú)需編寫(xiě)任何Native/JNI代碼歹篓,只需在Java接口中描述目標(biāo)Native Library的函數(shù)與結(jié)構(gòu)瘫证,JNA會(huì)自動(dòng)實(shí)現(xiàn)Java接口到Native Library的映射,可以方便地使用Java直接訪問(wèn)動(dòng)態(tài)鏈接庫(kù)中的函數(shù)庄撮。

JNA提供了一個(gè)動(dòng)態(tài)的C編寫(xiě)的轉(zhuǎn)發(fā)器背捌,可自動(dòng)實(shí)現(xiàn)Java和C的數(shù)據(jù)類型映射。DLL和SO是C函數(shù)的集合和容器洞斯,這與Java中的接口概念吻合毡庆,JNA把DLL/SO文件看作是接口,在JNA中定義一個(gè)接口相當(dāng)于定義了一個(gè)DLL/SO文件的描述文件,Java接口代表了動(dòng)態(tài)鏈接庫(kù)中發(fā)布的函數(shù)么抗。

使用JNA一般只適用于簡(jiǎn)單的C/C++庫(kù)毅否,如果接口、數(shù)據(jù)結(jié)構(gòu)復(fù)雜的化就不推薦乖坠,而且JNA也只提供了C/C++對(duì)Java的接口轉(zhuǎn)化搀突。

JNI

JNI全稱Java Native Interface即Java本地調(diào)用刀闷,從Java1.1開(kāi)始JNI標(biāo)準(zhǔn)成為Java平臺(tái)的一部分熊泵,實(shí)現(xiàn)了Java代碼和其他語(yǔ)言編寫(xiě)的代碼交互。JNI實(shí)現(xiàn)Java跨平臺(tái)的同時(shí)甸昏,也能與其他語(yǔ)言(如C顽分、C++)的動(dòng)態(tài)庫(kù)交互。

使用JNI可以實(shí)現(xiàn)Java程序中的函數(shù)調(diào)用Native語(yǔ)言編寫(xiě)的函數(shù)施蜜,Native一般指的是C/C++編寫(xiě)的函數(shù)卒蘸。使用JNI可以實(shí)現(xiàn)在Native程序的函數(shù)中調(diào)用Java層的函數(shù),也就是在C/C++程序中可以調(diào)用Java函數(shù)翻默。

JVM本身就是用Native語(yǔ)言編寫(xiě)的缸沃,JVM運(yùn)行在具體平臺(tái)上其本身是無(wú)法做到與平臺(tái)無(wú)關(guān)的。通過(guò)JNI技術(shù)可以對(duì)Java層屏蔽具體JVM實(shí)現(xiàn)上的差異修械,進(jìn)而實(shí)現(xiàn)Java本身的平臺(tái)無(wú)關(guān)性趾牧。

使用JNI并不簡(jiǎn)單,對(duì)一個(gè)編譯好的DLL/SO文件肯污,使用JNI調(diào)用時(shí)首先需要使用C另外編寫(xiě)一個(gè)DLL/SO共享庫(kù)翘单,使用SUN規(guī)定的數(shù)據(jù)結(jié)構(gòu)替代C的數(shù)據(jù)結(jié)構(gòu),再調(diào)用已有的DLL/SO中公布的函數(shù)蹦渣。然后在Java中載入這個(gè)DLL/SO哄芜,最后編寫(xiě)Java Native函數(shù)作為鏈接庫(kù)中函數(shù)的代理。使用JNI技術(shù)調(diào)用本地代碼比較繁瑣柬唯,因此引入了JNA技術(shù)认臊。

使用JNI調(diào)用C/C++的過(guò)程

時(shí)序 步驟 文件類型
1 編寫(xiě)Java類代碼 *.java
2 編譯成字節(jié)碼 *.class
3 產(chǎn)生C/C++頭文件 *.h
4 編寫(xiě)JNI實(shí)現(xiàn)代碼 *.c/cpp
5 編譯成鏈接庫(kù)文件 *.dll/so

使用JNA相比JNI調(diào)用動(dòng)態(tài)鏈接庫(kù)會(huì)有性能損耗,速度會(huì)降低幾倍锄奢。另外美尸,使用JNI不僅可以實(shí)現(xiàn)Java訪問(wèn)C函數(shù),也可實(shí)現(xiàn)C調(diào)用Java代碼斟薇。但JNA只能實(shí)現(xiàn)Java訪問(wèn)C函數(shù)师坎。

入門(mén)

JNA定義的接口繼承自com.sun.jna.Library接口,若DLL文件中的函數(shù)以stdcall方式輸出堪滨,接口應(yīng)繼承com.sun.jna.win32.StdCallLibrary接口胯陋。

例如:在SpringBoot中是用DLL文件

  1. 創(chuàng)建Maven工程,將DLL文件放到resources目錄下。
  2. 引入JNA相關(guān)的jar包
  3. 創(chuàng)建繼承自Library類的接口
  4. 接口中創(chuàng)建對(duì)象用于加載DLL/SO的類庫(kù)遏乔。
  5. 接口中聲明DLL/SO類庫(kù)頭文件中暴露的方法

引入依賴

$ vim pom.xml
<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna</artifactId>
    <version>5.4.0</version>
</dependency>

JNA引入動(dòng)態(tài)鏈接庫(kù)

通過(guò)JNA建立與動(dòng)態(tài)鏈接庫(kù)的映射义矛,只需創(chuàng)建一個(gè)接口來(lái)調(diào)用Native的loadLabrary()方法。

JNA建立與動(dòng)態(tài)鏈接庫(kù)中函數(shù)的對(duì)應(yīng)關(guān)系盟萨,只需在加載相應(yīng)類庫(kù)接口中聲明的函數(shù)即可凉翻。

JNA調(diào)用原生函數(shù)的模式

JNI中是用Native關(guān)鍵字來(lái)聲明一個(gè)Java方法表明外部的原生函數(shù),JNA中沒(méi)有使用Native表明原生函數(shù)而是使用Java Interface來(lái)表明動(dòng)態(tài)鏈接庫(kù)中全部原生函數(shù)捻激。

使用JNI加載動(dòng)態(tài)鏈接庫(kù)時(shí)必須使用System.loadLibrary()方法制轰,將專門(mén)為JNI編寫(xiě)的動(dòng)態(tài)鏈接庫(kù)載入,這個(gè)動(dòng)態(tài)鏈接庫(kù)實(shí)際上是真正動(dòng)態(tài)鏈接庫(kù)的代理胞谭。使用JNA無(wú)需編寫(xiě)作為代理的動(dòng)態(tài)鏈接庫(kù)垃杖,直接使用JNA庫(kù)的Native類中的loadLibrary()方法可直接加載最終的動(dòng)態(tài)鏈接庫(kù)。

類型映射

JNA使用的數(shù)據(jù)類型是Java的數(shù)據(jù)類型丈屹,而原生函數(shù)中是用的數(shù)據(jù)類型是原生函數(shù)編程語(yǔ)言的數(shù)據(jù)類型调俘,大多為C/Delphi/匯編等語(yǔ)言的數(shù)據(jù)類型。如果數(shù)據(jù)類型映射不一致旺垒,調(diào)用時(shí)可能會(huì)發(fā)生無(wú)法預(yù)知的行為導(dǎo)致調(diào)用失敗彩库。

JNA的難點(diǎn)在于編程語(yǔ)言之間的數(shù)據(jù)類型不一致,Java中是用的函數(shù)必須與鏈接庫(kù)中的函數(shù)的函數(shù)原型保持一致先蒋,這是JNA甚至是所有跨平臺(tái)調(diào)用的難點(diǎn)骇钦,因?yàn)镃/C++的類型與Java的類型是不一樣的,因此必須將其裝換為Java對(duì)應(yīng)的數(shù)據(jù)類型鞭达,這就是類型映射(Type Mappings)司忱。類型映射的難點(diǎn)在于結(jié)構(gòu)體、指針和函數(shù)回調(diào)畴蹭。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末坦仍,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子叨襟,更是在濱河造成了極大的恐慌繁扎,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,427評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件糊闽,死亡現(xiàn)場(chǎng)離奇詭異梳玫,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)右犹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)提澎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人念链,你說(shuō)我怎么就攤上這事盼忌』矗” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,747評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵谦纱,是天一觀的道長(zhǎng)看成。 經(jīng)常有香客問(wèn)我,道長(zhǎng)跨嘉,這世上最難降的妖魔是什么川慌? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,939評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮祠乃,結(jié)果婚禮上梦重,老公的妹妹穿的比我還像新娘。我一直安慰自己跳纳,他們只是感情好忍饰,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布贪嫂。 她就那樣靜靜地躺著寺庄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪力崇。 梳的紋絲不亂的頭發(fā)上斗塘,一...
    開(kāi)封第一講書(shū)人閱讀 51,737評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音亮靴,去河邊找鬼馍盟。 笑死,一個(gè)胖子當(dāng)著我的面吹牛茧吊,可吹牛的內(nèi)容都是我干的贞岭。 我是一名探鬼主播,決...
    沈念sama閱讀 40,448評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼搓侄,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼瞄桨!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起讶踪,我...
    開(kāi)封第一講書(shū)人閱讀 39,352評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤芯侥,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后乳讥,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體柱查,經(jīng)...
    沈念sama閱讀 45,834評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評(píng)論 3 338
  • 正文 我和宋清朗相戀三年云石,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了唉工。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,133評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡汹忠,死狀恐怖淋硝,靈堂內(nèi)的尸體忽然破棺而出告嘲,到底是詐尸還是另有隱情,我是刑警寧澤奖地,帶...
    沈念sama閱讀 35,815評(píng)論 5 346
  • 正文 年R本政府宣布橄唬,位于F島的核電站,受9級(jí)特大地震影響参歹,放射性物質(zhì)發(fā)生泄漏仰楚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評(píng)論 3 331
  • 文/蒙蒙 一犬庇、第九天 我趴在偏房一處隱蔽的房頂上張望僧界。 院中可真熱鬧,春花似錦臭挽、人聲如沸捂襟。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,022評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)葬荷。三九已至,卻和暖如春纽帖,著一層夾襖步出監(jiān)牢的瞬間宠漩,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,147評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工懊直, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留扒吁,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,398評(píng)論 3 373
  • 正文 我出身青樓室囊,卻偏偏與公主長(zhǎng)得像雕崩,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子融撞,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容