久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

android 動態(tài)注冊JNI函數(shù)過程源碼分析

 清凈明誨 2013-12-26
private static native final void native_init();

 

那是怎么知道是這個方法的呢?
MediaRecorder.java位于android.media包中,,所以native_init的全路徑是android.media.MediaRecorder.native_init,。顯而易見,將“.”替換成“_”就是jni函數(shù)的名字了,。這里說的就是JNI函數(shù)的注冊問題,,就是將java層的native函數(shù)和JNI層函數(shù)的具體實現(xiàn)關(guān)聯(lián)起來。
JNI函數(shù)的注冊有兩種方法,,一種是靜態(tài)方法,,需要用javah為每個聲明了native函數(shù)的java類編譯出的class文件生成一個頭文件,另一種是動態(tài)注冊,通過數(shù)據(jù)結(jié)構(gòu)保存關(guān)聯(lián)關(guān)系實現(xiàn)注冊,,這里主要介紹動態(tài)注冊,。
動態(tài)注冊
動態(tài)注冊需要一個數(shù)據(jù)結(jié)構(gòu)去保存相關(guān)的關(guān)聯(lián)關(guān)系,這個結(jié)構(gòu)(在jni.h中聲明)是:
復制代碼
typedef struct {
 
 
const char* name; //java中native函數(shù)的名字
 
 
const char* signature; //Java函數(shù)的簽名信息,,用字符串表示,,是參數(shù)類型和返回值類型的組合
 
 
void* fnPtr; } JNINativeMethod; //JNI層函數(shù)的函數(shù)指針,void*類型
復制代碼

 

在JNI層中(android_media_MediaRecorder.cpp)是如何使用這個結(jié)構(gòu)體的:
復制代碼
 
static JNINativeMethod gMethods[] = {
 
{"native_init","()V",(void *)android_media_MediaRecorder_native_init},
 
};
 
// This function only registers the native methods, and is called from
// JNI_OnLoad in android_media_MediaPlayer.cpp
int register_android_media_MediaRecorder(JNIEnv *env) //什么時候會調(diào)用呢,?后面介紹
{
return AndroidRuntime::registerNativeMethods(env,
"android/media/MediaRecorder", gMethods, NELEM(gMethods));
}
復制代碼

 

利用AndroidRuntime類提供的registerNativeMethods函數(shù)完成注冊工作
復制代碼
 
/*
* Register native methods using JNI.
*/
/*static*/ int AndroidRuntime::registerNativeMethods(JNIEnv* env,
const char* className, const JNINativeMethod* gMethods, int numMethods) //位于AndroidRuntime.cpp
{
return jniRegisterNativeMethods(env, className, gMethods, numMethods);
}
 
/*
* Register native JNI-callable methods.
*
* "className" looks like "java/lang/String".
*/
int jniRegisterNativeMethods(JNIEnv* env, const char* className,const JNINativeMethod* gMethods, int numMethods) //位于JNIHelp.c
{ jclass clazz;
LOGV("Registering %s natives\n", className);
clazz = (*env)->FindClass(env, className);
if (clazz == NULL)
{
LOGE("Native registration unable to find class '%s'\n", className); return -1;
}
if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0)
{
LOGE("RegisterNatives failed for '%s'\n", className); return -1;
} return 0;}
復制代碼

 

實際上所有的注冊工作最后就是調(diào)用:
(*env)->RegisterNatives(env,clazz,gMethods,numMethods)完成,。那么這些動態(tài)注冊的函數(shù)是什么時候和什么地方調(diào)用的呢?其實,,當Java層通過System.loadLibrary加載完JNI動態(tài)庫之后,,就會查找?guī)熘薪蠮NI_OnLoad函數(shù),通過調(diào)用它完成動態(tài)注冊的工作,。
復制代碼
externint register_android_media_MediaRecorder(JNIEnv *env);
jint JNI_OnLoad(JavaVM* vm, void* reserved) //JavaVM* vm是Java虛擬機在JNI層的對象,,每一個java進程只有一個JVM
{
JNIEnv* env = NULL; //每一個線程有一個JNIEnv對象
jint result = -1;
 
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
LOGE("ERROR: GetEnv failed\n");
goto bail;
}
 
 
if (register_android_media_MediaRecorder(env) < 0) { //動態(tài)注冊MediaRecorder的JNI函數(shù)
LOGE("ERROR: MediaRecorder native registration failed\n");
goto bail;
} /* success -- return valid version number */
result = JNI_VERSION_1_4;
 
bail:
return result;
}
復制代碼

 

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,,謹防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多