簡(jiǎn)介
- 本節(jié)示例怎么使 Java應(yīng)用程序 通過(guò) JNI 調(diào)用 C語(yǔ)言 輸出
Hello World!
。
流程
- 創(chuàng)建一個(gè)
HelloWorld.java
文件并聲明原生方法肃弟。
- 使用 javac 編譯
HelloWorld.java
耸黑,生成HelloWorld.class
文件桃煎。
- 使用 javah 生成C頭文件
HelloWorld.h
,該頭文件包含了原生函數(shù)實(shí)現(xiàn)的原型崎坊。
- 新建文件
HelloWorld.c
并按照HelloWorld.h
中聲明的原生函數(shù)原型實(shí)現(xiàn)原生代碼备禀。
- 將
HelloWorld.c
構(gòu)建成為一個(gè)原生庫(kù)洲拇,生成HelloWorld.dll
或者HelloWorld.so
奈揍。
- 使用 Java 運(yùn)行HelloWorld程序,
HelloWorld.class
和HelloWorld.dll/so
會(huì)在運(yùn)行時(shí)被加載赋续。
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è)部分:
- 一個(gè)靜態(tài)代碼塊男翰,用來(lái)加載 動(dòng)態(tài)鏈接庫(kù) 。
- 一個(gè)主函數(shù)作為 Java應(yīng)用程序 入口纽乱,并在主函數(shù)中調(diào)用
print
蛾绎。
- 一個(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ù)制 DLL 到 Java 項(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ò))
- File -> Settings -> External Tools公荧。
- 點(diǎn)擊 “+” 按鈕。
-
Name :
生成頭文件
同规。
-
Group :
JNI
循狰。
-
Options : 全部勾選。
-
Show in : 全部勾選捻浦。
-
Program :
$JDKPath$\bin\javah.exe
晤揣。
-
Parameters :
-jni -v -d $FileDir$ $FileClass$
。$FileDir$
表示輸出目錄朱灿,將$FileDir$
設(shè)置為 CLion 項(xiàng)目目錄昧识。
-
Working directory :
$SourcepathEntry$
。
- 點(diǎn)擊確定盗扒。
2. 生成
- 選擇對(duì)應(yīng)的java文件跪楞。
- 右鍵 -> JNI -> Generate Header File。
- 在
$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
接口指針校焦。
-
jobject
:HelloWorld
對(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)系作者