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