摘要:初識本地接口概述是用于和本地代碼進(jìn)行交互操作的。針對的是語言,而不是。當(dāng)然,最初也有運(yùn)行的比較慢的原因,但隨著的不斷發(fā)展,編寫的代碼有時已經(jīng)不遜于一些的代碼了。聲明通過關(guān)鍵字標(biāo)識,提醒編譯器該方法在外部定義。
初識 JNI
JNI, Java Native Interface(Java本地接口).概述
JNI 是用于和本地 C 代碼進(jìn)行交互操作的API。實(shí)際上可以通過許多語言編寫,如C++、C#,本質(zhì)上 Java 調(diào)用的是 dll/so 庫 。此處說是和本地 C 代碼互操作是因?yàn)?JNI API的支持。JNI API針對的是 C 語言,而不是Java。
JNI 的出現(xiàn)的原因有一些是為了彌補(bǔ)一些無法通過 Java 平臺實(shí)現(xiàn)的功能。比如 Windows 的注冊表,這是 Windows 獨(dú)有的東西,Java 并沒有現(xiàn)成可以操作它的 API。
也有一些原因是非 Java 語言編寫的代碼已經(jīng)經(jīng)過了大量的測試,無需重新用 Java 實(shí)現(xiàn)一套。
當(dāng)然,最初也有 JVM 運(yùn)行的比較慢的原因,但隨著 JVM 的不斷發(fā)展,Java編寫的代碼有時已經(jīng)不遜于一些 C/C++ 的代碼了。
JNI 有著上述的一些好處,隨著而來的是它會帶來相應(yīng)語言的缺點(diǎn),
比如會引入 C 語言的無效指針造成的內(nèi)存覆寫問題等等。
所以說 JNI 實(shí)際上使用范圍相對較窄,Web 后端方面用的比較少,安卓端用的相對更多一點(diǎn)。
示例 Hello World以下為一個簡單的示例
Java 部分首先在在 Java 中聲明 dll/so 庫中定義的函數(shù)。
聲明通過 native 關(guān)鍵字標(biāo)識,提醒編譯器該方法在外部定義。
// 為了簡單,此處沒有package public class HelloNative { public static native void greeting(); }C 部分
然后在 C 中定義函數(shù),函數(shù)名有如下要求:
Java_包名_類名_方法名 。(其中的.號都要改為 _下劃線)
如果類名中含有非 ASCII 碼值,或說大于 uoo7F 的 Unicode 字符,用 _0xxxx 來代替。
(xxxx 是該字符的Unicode值的4個十六進(jìn)制數(shù)序列)
方法重載需要在名稱后加兩個下劃線,后再加上已編碼的類型。
為了避免在函數(shù)定義時候出錯,Java 提供了 javah 工具完成函數(shù)名的編寫操作。
javah 是通過類文件來生成相應(yīng)的文件的,所以源代碼必須要先編譯才可以。
javah HelloNative
通過如上命令,會生成一個 HelloNative.h 的文件,這個文件包含了 greeting() 方法的聲明。
復(fù)制該文件,改為 .c 文件,去掉一些不需要的東西,然后包含 #include "HelloNative.h" 即可。
然后將方法聲明改為方法實(shí)現(xiàn),在方法實(shí)現(xiàn)中編寫具體的代碼。
JNIEXPORT void JNICALL Java_HelloNative_greeting (JNIEnv* env, jclass cl) { printf("Hello Native World!"); }
之后就是編譯代碼了,此處僅粘貼個人測試過的命令,為 Windows 上的 MinGW64 上的 gcc 。
gcc -I "jdk/include" -I "jdk/include/win32" -D __int64="long long" -shared -o HelloNative.dll HelloNative.c
關(guān)于 -D __int64="long long" 參數(shù)的說明:
Windows 上的 jni_md.h 含有聲明 typedef __int64 jlong; ,它專用于 cl 的。如果使用 gcc 需要設(shè)置 -D __int64="long long"
或者也可以修改此文件,如:
#ifdef __GNUC__ typedef long long jlong; #else typedef __int64 jlong; #endif調(diào)用
創(chuàng)建 HelloNativeTest 類以供測試:
public class HelloNativeTest { static { // 此處不需要 dll/so 后綴,系統(tǒng)會自動根據(jù)系統(tǒng)不同換后綴 System.loadLibrary("HelloNative"); } public static void main(String[] args){ HelloNative.greeting(); } }
記住這里打印的消息是通過 printf 打印的,不是 java 的代碼打印的。
注:
一些本地代碼的共享庫必須先運(yùn)行初始化代碼,可以將初始化代碼放置到JNI_OnLoad方法中,如果提供該方法,則虛擬機(jī)關(guān)
閉時會調(diào)用JNI_OnUnload方法,原型如下:
jint JNI_OnLoad(JavaVM* vm, void* reserved); //返回它所需的虛擬機(jī)的最低版本,如JNI_VERSION_1_2 void JNI_OnUnload(JavaVM* vm, void* reserved);
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/72634.html
摘要:介紹了在中配置的開發(fā)環(huán)境開發(fā)環(huán)境配置,開發(fā)環(huán)境配置完成之后,就要寫一下著名的程序了。尤其是但是并不妨礙你使用其他語言,只要調(diào)用約定支持就可以了。是指定所在的目錄,項(xiàng)目成功之后,會在目錄里生成文件。是包名加上類名。 介紹了在Android Studio中配置NDK的開發(fā)環(huán)境:Android Studio NDK開發(fā)-環(huán)境配置,NDK開發(fā)環(huán)境配置完成之后,就要寫一下著名的Hello Wor...
閱讀 721·2021-11-22 13:54
閱讀 3084·2021-09-26 10:16
閱讀 3519·2021-09-08 09:35
閱讀 1593·2019-08-30 15:55
閱讀 3440·2019-08-30 15:54
閱讀 2086·2019-08-30 10:57
閱讀 506·2019-08-29 16:25
閱讀 885·2019-08-29 16:15