【Android】JNI靜態(tài)與動(dòng)態(tài)注冊(cè)介紹
點(diǎn)擊關(guān)注,與你共同成長(zhǎng)!

【Android】JNI靜態(tài)與動(dòng)態(tài)注冊(cè)介紹
JNI的兩種注冊(cè)機(jī)制:靜態(tài)注冊(cè)和動(dòng)態(tài)注冊(cè).
JNI介紹
JNI(Java Native Interface),即Java本地接口,JNI是Java調(diào)用Native 語(yǔ)言的一種特性。通過(guò)JNI可以使得Java與C/C++機(jī)型交互.
方式:
靜態(tài)注冊(cè) 動(dòng)態(tài)注冊(cè):需要提供Java中Native方法的方法簽名和Native層中對(duì)應(yīng)的實(shí)現(xiàn)函數(shù)。
靜態(tài)注冊(cè)
要求C/C++層的函數(shù)名符合某種特定的要求:包含Java中Native方法的目錄信息和方法名。
Example
Java
package cn.com.codingce.ndkpractice;
public native String stringFromJNI();
C++
extern "C"
JNIEXPORT jstring JNICALL
Java_cn_com_codingce_ndkpractice_MainActivity_stringFromJNI(JNIEnv *env, jobject thiz) {
std::string hello = "Hello from C++";
//crashTest();
return env->NewStringUTF(hello.c_str());
}
按照以上規(guī)則進(jìn)行命名,在調(diào)用到Native的方法時(shí),JVM會(huì)去查找是否存在對(duì)應(yīng)函數(shù)名的函數(shù),以此實(shí)現(xiàn)靜態(tài)注冊(cè)。
動(dòng)態(tài)注冊(cè)
動(dòng)態(tài)注冊(cè)相對(duì)于靜態(tài)注冊(cè),優(yōu)點(diǎn)是不再根據(jù)特定路徑查找函數(shù)的實(shí)現(xiàn),帶來(lái)兩個(gè)好處:
沒(méi)有了冗雜的函數(shù)名,適用于大型項(xiàng)目開(kāi)發(fā)。 由于不再根據(jù)Native函數(shù)查找對(duì)應(yīng)的JNI層函數(shù),所以首次調(diào)用速度比靜態(tài)注冊(cè)快。
開(kāi)發(fā)者需要自行提供Java層和C/C++層中的映射關(guān)系。
一種可行的方法是基于JNI重載JNI_OnLoad(),在其中對(duì)函數(shù)進(jìn)行動(dòng)態(tài)注冊(cè)。
Example
Java
package cn.com.codingce.ndkpractice.utils;
public static native void logInit(String logFilePath, String logName, int logfileLevel, int logScreenLevel);
C++
此步驟涉及到如何獲取Java函數(shù)。
static JNINativeMethod nativeUtilsMethods[] = {
{"logInit", "(Ljava/lang/String;Ljava/lang/String;II)V", (void *) localLogInit},
{"logJni", "(ILjava/lang/String;)V", (void *) logJni},
{"logClose", "()V", (void *) logClose},
};
static void nativeLogUtilsRegisterNatives(JNIEnv *jniEnv) {
if (jniEnv == nullptr) {
return;
}
jclass clazz = nullptr;
do {
clazz = jniEnv->FindClass("cn/com/codingce/ndkpractice/utils/LogUtils");
if (clazz == nullptr) {
diagnosis_assert(!"FindClass LogUtils error!");
break;
}
if (jniEnv->RegisterNatives(clazz, nativeUtilsMethods,
std::extent<decltype(nativeUtilsMethods)>::value) != 0) {
diagnosis_assert(!"RegisterNatives error!");
break;
}
} while (false);
if (jniEnv->ExceptionCheck() == JNI_TRUE) {
jniEnv->ExceptionClear();
}
if (clazz != nullptr) {
jniEnv->DeleteLocalRef(clazz);
}
}
重載JNI_OnLoad函數(shù),并在其中調(diào)用nativeLogUtilsRegisterNatives函數(shù)
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv *jniEnv{nullptr};
if (vm->GetEnv((void **) &jniEnv, JNI_VERSION_1_6) != JNI_OK) {
diagnosis_assert(!"JNI version error!");
return JNI_EVERSION;
}
nativeLogUtilsRegisterNatives(jniEnv);
return JNI_VERSION_1_6;
}
更多內(nèi)容:
Github:https://github.com/xzMhehe
Gitee:https://gitee.com/codingce

以上,便是今天的分享,希望大家喜歡,覺(jué)得內(nèi)容不錯(cuò)的,歡迎「分享」「贊」或者點(diǎn)擊「在看」支持,謝謝各位。
