★02.入門(mén)

簡(jiǎn)介

  • 本節(jié)示例怎么使 Java應(yīng)用程序 通過(guò) JNI 調(diào)用 C語(yǔ)言 輸出Hello World!

流程

  1. 創(chuàng)建一個(gè)HelloWorld.java文件并聲明原生方法肃弟。
  2. 使用 javac 編譯HelloWorld.java耸黑,生成HelloWorld.class文件桃煎。
  3. 使用 javah 生成C頭文件HelloWorld.h,該頭文件包含了原生函數(shù)實(shí)現(xiàn)的原型崎坊。
  4. 新建文件HelloWorld.c并按照HelloWorld.h中聲明的原生函數(shù)原型實(shí)現(xiàn)原生代碼备禀。
  5. HelloWorld.c構(gòu)建成為一個(gè)原生庫(kù)洲拇,生成HelloWorld.dll或者HelloWorld.so奈揍。
  6. 使用 Java 運(yùn)行HelloWorld程序,HelloWorld.classHelloWorld.dll/so會(huì)在運(yùn)行時(shí)被加載赋续。
JNI Hello World 示意圖

HelloWorld示例

1. 創(chuàng)建HelloWorld.java

代碼

public class HelloWorld {
    static {
        // "HelloWorld" 表明載入HelloWorld.dll
        System.loadLibrary("HelloWorld");
    }

    public static void main(String[] args) {
        new HelloWorld().print();
    }

    private native void print();
}

解說(shuō)

  • 上述代碼主要包含三個(gè)部分:
    1. 一個(gè)靜態(tài)代碼塊男翰,用來(lái)加載 動(dòng)態(tài)鏈接庫(kù)
    2. 一個(gè)主函數(shù)作為 Java應(yīng)用程序 入口纽乱,并在主函數(shù)中調(diào)用print蛾绎。
    3. 一個(gè)原生函數(shù)print的聲明,由原生代碼實(shí)現(xiàn)。
  • 包含原生代碼的 動(dòng)態(tài)鏈接庫(kù) 一定要提前加載租冠。
  • print函數(shù)聲明中的native修飾符表示該函數(shù)是使用其他語(yǔ)言實(shí)現(xiàn)的鹏倘。

2. 生成HelloWorld.class

  • 編譯產(chǎn)生HelloWorld.class

3. 使用CLion創(chuàng)建C/C++項(xiàng)目

  • 保證 CLion 使用的是 MinGW-w64 而不是 MinGW-32 顽爹。
  • 設(shè)置JAVAHOME環(huán)境變量纤泵,指向 jdk 目錄。
  • 通過(guò)CMakeList.txt設(shè)置 JNI 包含目錄镜粤。
  • 通過(guò)CMakeList.txt設(shè)置構(gòu)建完畢后自動(dòng)復(fù)制 DLLJava 項(xiàng)目目錄下捏题。
  • CMakeList.txt文件參考,
cmake_minimum_required(VERSION 3.7)
project(JNI_c)

set(CMAKE_C_STANDARD 11)

# 相當(dāng)于 SOURCE_FILES = "HelloWorld.h HelloWorld.c"
set(SOURCE_FILES HelloWorld.h HelloWorld.c)
add_library(JNI_c SHARED ${SOURCE_FILES})

include_directories($ENV{JAVAHOME}/include)
include_directories($ENV{JAVAHOME}/include/win32)

# 設(shè)置輸出DLL的名字前綴
set_target_properties(JNI_c PROPERTIES PREFIX "")
# 設(shè)置輸出DLL的名字肉渴,此處輸出HelloWorld.dll
set_target_properties(JNI_c PROPERTIES OUTPUT_NAME "HelloWorld")

# 構(gòu)建完后復(fù)制DLL到指定目錄
add_custom_command(TARGET JNI_c POST_BUILD                     # JNI_c是項(xiàng)目名稱(chēng)
        COMMAND ${CMAKE_COMMAND} -E copy_if_different
        "$<TARGET_FILE_DIR:JNI_c>/HelloWorld.dll"           # input dir
        "C:/ProgramProjects/Java/JNI")                         # output dir

4. 生成HelloWorld.h

1. 配置 IDEA 中生成頭文件規(guī)則(已配置則跳過(guò))

  1. File -> Settings -> External Tools公荧。
  2. 點(diǎn)擊 “+” 按鈕。
    1. Name : 生成頭文件同规。
    2. Group : JNI循狰。
    3. Options : 全部勾選。
    4. Show in : 全部勾選捻浦。
    5. Program : $JDKPath$\bin\javah.exe晤揣。
    6. Parameters : -jni -v -d $FileDir$ $FileClass$$FileDir$表示輸出目錄朱灿,將$FileDir$設(shè)置為 CLion 項(xiàng)目目錄昧识。
    7. Working directory : $SourcepathEntry$
  3. 點(diǎn)擊確定盗扒。

2. 生成

  1. 選擇對(duì)應(yīng)的java文件跪楞。
  2. 右鍵 -> JNI -> Generate Header File。
  3. $FileDir$對(duì)應(yīng)的目錄里生成了HelloWorld.h侣灶。

3. 解說(shuō)HelloWorld.h文件

代碼

/*
 * Class:     HelloWorld
 * Method:    print
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HelloWorld_print
  (JNIEnv * , jobject);

解說(shuō)

  • 注釋部分:
    • Class :函數(shù)來(lái)自的那一個(gè)類(lèi)的名字甸祭。
    • Method :這個(gè)函數(shù)的名字。
    • Signature :這個(gè)函數(shù)的簽名褥影。
      • ()V:函數(shù)的簽名為void ()池户。
      • (IFC)D:這個(gè)函數(shù)的double (int, float, char)
  • 代碼部分:
    • void:原方法的返回值凡怎。
    • JNIEnv *:一個(gè)JNIEnv接口指針校焦。
    • jobjectHelloWorld對(duì)象本身,有點(diǎn)像 C++ 中的this指針统倒。

5. 實(shí)現(xiàn)HelloWorld.c

#include <jni.h>

#ifdef __cplusplus
extern "C" {
#endif

/*
 * Class:     HelloWorld
 * Method:    print
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HelloWorld_print(JNIEnv * env, jobject obj) {
    printf("Hello World!\n");
}

#ifdef __cplusplus
}
#endif

5. 生成動(dòng)態(tài)鏈接庫(kù)并運(yùn)行

  • Clion 中構(gòu)建項(xiàng)目寨典,生成 DLL 到對(duì)應(yīng)目錄。
  • 設(shè)置 IDEA 中的 Run/Debug Configurations
    • VM Options 設(shè)置為-Djava.library.path=C:\ProgramProjects\Java\JNI\
  • 運(yùn)行程序房匆。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末耸成,一起剝皮案震驚了整個(gè)濱河市报亩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌井氢,老刑警劉巖弦追,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異花竞,居然都是意外死亡骗卜,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén)左胞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)寇仓,“玉大人,你說(shuō)我怎么就攤上這事烤宙”榉常” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵躺枕,是天一觀的道長(zhǎng)服猪。 經(jīng)常有香客問(wèn)我,道長(zhǎng)拐云,這世上最難降的妖魔是什么罢猪? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮叉瘩,結(jié)果婚禮上膳帕,老公的妹妹穿的比我還像新娘。我一直安慰自己薇缅,他們只是感情好危彩,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著泳桦,像睡著了一般汤徽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上灸撰,一...
    開(kāi)封第一講書(shū)人閱讀 49,760評(píng)論 1 289
  • 那天谒府,我揣著相機(jī)與錄音,去河邊找鬼浮毯。 笑死完疫,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的亲轨。 我是一名探鬼主播趋惨,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼鸟顺,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼惦蚊!你這毒婦竟也來(lái)了器虾?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蹦锋,失蹤者是張志新(化名)和其女友劉穎兆沙,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體莉掂,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡葛圃,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了憎妙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片库正。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖厘唾,靈堂內(nèi)的尸體忽然破棺而出褥符,到底是詐尸還是另有隱情,我是刑警寧澤抚垃,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布喷楣,位于F島的核電站,受9級(jí)特大地震影響鹤树,放射性物質(zhì)發(fā)生泄漏铣焊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一罕伯、第九天 我趴在偏房一處隱蔽的房頂上張望曲伊。 院中可真熱鬧,春花似錦追他、人聲如沸熊昌。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)婿屹。三九已至,卻和暖如春推溃,著一層夾襖步出監(jiān)牢的瞬間昂利,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工铁坎, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蜂奸,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓硬萍,卻偏偏與公主長(zhǎng)得像扩所,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子朴乖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348

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

  • native關(guān)鍵字說(shuō)明其修飾的方法是一個(gè)原生態(tài)方法祖屏,方法對(duì)應(yīng)的實(shí)現(xiàn)不是在當(dāng)前文件助赞,而是在用其他語(yǔ)言(如C和C++)...
    時(shí)待吾閱讀 547評(píng)論 0 2
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,742評(píng)論 25 707
  • 你有沒(méi)有想過(guò)從來(lái)沒(méi)愛(ài)過(guò)什么人會(huì)是什么樣的感覺(jué),會(huì)過(guò)怎么樣的人生袁勺,會(huì)變成一個(gè)怎樣的人雹食。吶,我就是那個(gè)長(zhǎng)了二十年沒(méi)...
    胖胖的張二十閱讀 428評(píng)論 0 2
  • 集期丰。人多群叶,卻不忙。 臨門(mén)而立钝荡,看熙熙攘攘人來(lái)人往街立,人間百態(tài),世俗民情埠通,盡在眼底几晤。大俗,卻不失熱鬧植阴。 對(duì)...
    雪下冰閱讀 395評(píng)論 0 2