使用JNI(Java Native Interface)的總結(jié)

目錄

  1. 什么是JNI?
  2. 為什么使用JNI枯饿?
  3. 怎么使用JNI?
  4. 在IntelliJ IDEA里使用JNI

<h2 id="1"> 1. 什么是JNI诡必?</h2>
JNI(Java Native Interface) Java本地接口奢方,又叫Java原生接口。它允許Java調(diào)用C/C++的代碼,同時(shí)也允許在C/C++中調(diào)用Java的代碼爸舒◇郑可以把JNI理解為一個(gè)橋梁,連接Java和底層碳抄。其實(shí)根據(jù)字面意思愉老,JNI就是一個(gè)介于Java層和Native層的接口,而Native層就是C/C++層面剖效。

<h2 id="2"> 2. 為什么使用JNI嫉入?</h2>
一般情況下都是從Java的角度來使用JNI,也就是說在Java中調(diào)用C/C++語(yǔ)言來實(shí)現(xiàn)一些操作璧尸。所以從Java角度來說使用JNI具有以下的優(yōu)點(diǎn):

  1. 能夠重復(fù)使用一些現(xiàn)成的咒林、具有相同功能的的C/C++代碼
  2. 因?yàn)镃/C++是偏向底層的語(yǔ)言,所以使用C/C++能夠更加的高效爷光,而且也使得Java能夠訪問操作系統(tǒng)中一些底層的特性垫竞。

<h2 id="3"> 3. 怎么使用JNI?</h2>
這里所說的使用JNI是指從Java層調(diào)用C/C++代碼蛀序,一般的使用步驟都是使用Java定義一個(gè)類欢瞪,然后在該類中聲明一個(gè)native的方法,接著使用C/C++來實(shí)現(xiàn)這個(gè)方法的方法體徐裸。

3.1 使用Java聲明native方法

方法一:TestJNI.java

public class TestJNI{
    public native void sayHello();
}

在聲明native方法的時(shí)候還可以規(guī)定具體的包遣鼓,例如:

方法二:TestJNI.java

package jnilib;
public class TestJNI{
    public native void sayHello();
}

這兩種方式都可以,但是使用這兩種方式聲明native方法重贺,最后生成的動(dòng)態(tài)庫(kù)時(shí)骑祟,在IntelliJ IDEA中的使用方法卻是不一樣(這一點(diǎn)在最后會(huì)進(jìn)行說明),這里我們采用方法二气笙。

3.2 編譯聲明的Java文件

先使用javac編譯生成.class文件

javac -d . TestJNI.java

因?yàn)樵谠创a中使用了package的命令次企,所以編譯的時(shí)候需要用"-d ."參數(shù),其中"."表示在當(dāng)前目錄生成 jnilib文件夾來存放編譯生成.class文件

再使用javah編譯生成.h文件

javah jnilib.TestJNI

需要在類文件名前面加上包名潜圃,編譯完成之后缸棵,會(huì)在當(dāng)前目錄生成jnilib_TestJNI.h的文件,接下來我們用C語(yǔ)言來實(shí)現(xiàn)剛剛聲明的函數(shù)時(shí)谭期,需要include這個(gè)頭文件堵第。

jnilib_TestJNI.h:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class jnilib_TestJNI */

#ifndef _Included_jnilib_TestJNI
#define _Included_jnilib_TestJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     jnilib_TestJNI
 * Method:    sayHello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_jnilib_TestJNI_sayHello
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

其中 JNIEXPORT void JNICALL Java_jnilib_TestJNI_sayHello(JNIEnv *, jobject); 就是我們用Java聲明的native函數(shù)經(jīng)過轉(zhuǎn)換之后的形式稚晚,當(dāng)我們用C語(yǔ)言來實(shí)現(xiàn)的時(shí)候需要使用這個(gè)函數(shù)的聲明。

3.3 用C語(yǔ)言來實(shí)現(xiàn)函數(shù)

創(chuàng)建一個(gè)TestJNI.c文件:

TestJNI.c

#include <stdio.h>
#include "jnilib_TestJNI.h"

JNIEXPORT void JNICALL Java_jnilib_TestJNI_sayHello(JNIEnv *env, jobject object){
    printf("Hello World!\n");
}

3.4 生成動(dòng)態(tài)庫(kù)文件

這需要注意的是在不同的操作系統(tǒng)型诚,能夠生成的動(dòng)態(tài)庫(kù)文件也是不一樣的,在Windows中鸳劳,要生成.dll文件狰贯,在Linux中要生成.so文件,在Mac OS X中要生成.jnilib文件赏廓。同時(shí)定義生成的庫(kù)文件名的時(shí)候也要遵循:lib+文件名+擴(kuò)展名 的原則涵紊。本例中我們?cè)贛ac OS X中所以我們定義生成的庫(kù)文件為:libTestJNI.jnilib

makefile:

CC=gcc
CFLAGS=I.

libTestJNI.jnilib : TestJNI.c
    $(CC) -fPIC -I/Library/java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/include -I/Library/java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/include/darwin -shared -o $@ $^

執(zhí)行make之后獲得 libTestJNI.jnilib其中/Library/java/JavaVirtualMachines/jdk1.8.0_91.jdk為Java的安裝目錄幔摸。

3.5 使用生成的動(dòng)態(tài)庫(kù)文件

使用Java調(diào)用生成的動(dòng)態(tài)庫(kù)

Demo.java

import jnilib.TestJNI;
public class Demo{
    static{
            try{
                System.loadLibrary("TestJNI");
            }catch(UnsatisfiedLinkError e){
                System.err.println("Native code library failed to load.\n" + e);
                System.exit(1);
            }
        }

    public static void main(String[] args) {
        TestJNI test = new TestJNI();
        test.sayHello();
    }
}

編譯摸柄、執(zhí)行后得到結(jié)果:

Hello World!

<h2 id="4"> 4. 在IntelliJ IDEA里使用JNI?</h2>
利用IntelliJ IDEA創(chuàng)建項(xiàng)目既忆,這里因?yàn)槲覀冎奥暶鱪ative函數(shù)的時(shí)候使用了package驱负,所以我們需要在src/main/java的目錄下創(chuàng)建一個(gè)文件夾為jnilib,把我們之前生成的TestJNI.java libTest.jnilib 文件放到該目錄下患雇。接著我們創(chuàng)建Demo文件來調(diào)用生成的動(dòng)態(tài)庫(kù)跃脊,但是如果我們此時(shí)運(yùn)行我們的Demo的話會(huì)產(chǎn)生下面的異常:

java.lang.UnsatisfiedLinkError: no GetDownloadID in java.library.path

這時(shí)我們需要點(diǎn)擊EditConfigurationsVM Options 一欄填上 -Djava.library.path="/Users/xiangang/JavaWebLearning/DownloadID/src/main/java/jnilib"雙引號(hào)里面的路徑就是你剛剛創(chuàng)建的 jnilib文件夾的路徑。

如果我們?cè)诼暶鱪ative函數(shù)的時(shí)候沒有使用package命令苛吱,則我們必須把以上的兩個(gè)文件放在src/main/java目錄下酪术,而且調(diào)用這個(gè)庫(kù)文件的文件也不能使用package。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末翠储,一起剝皮案震驚了整個(gè)濱河市绘雁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌援所,老刑警劉巖庐舟,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異任斋,居然都是意外死亡继阻,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門废酷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瘟檩,“玉大人,你說我怎么就攤上這事澈蟆∧粒” “怎么了?”我有些...
    開封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵趴俘,是天一觀的道長(zhǎng)睹簇。 經(jīng)常有香客問我奏赘,道長(zhǎng),這世上最難降的妖魔是什么太惠? 我笑而不...
    開封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任磨淌,我火速辦了婚禮,結(jié)果婚禮上凿渊,老公的妹妹穿的比我還像新娘梁只。我一直安慰自己,他們只是感情好埃脏,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開白布搪锣。 她就那樣靜靜地躺著,像睡著了一般彩掐。 火紅的嫁衣襯著肌膚如雪构舟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天堵幽,我揣著相機(jī)與錄音狗超,去河邊找鬼。 笑死朴下,一個(gè)胖子當(dāng)著我的面吹牛抡谐,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播桐猬,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼麦撵,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了溃肪?” 一聲冷哼從身側(cè)響起免胃,我...
    開封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎惫撰,沒想到半個(gè)月后羔沙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡厨钻,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年扼雏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片夯膀。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡诗充,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出诱建,到底是詐尸還是另有隱情蝴蜓,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站茎匠,受9級(jí)特大地震影響格仲,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜诵冒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一凯肋、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧汽馋,春花似錦否过、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)药磺。三九已至告组,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間癌佩,已是汗流浹背木缝。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留围辙,地道東北人我碟。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像姚建,于是被迫代替她去往敵國(guó)和親矫俺。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

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