ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2,阿里+头条+腾讯等大厂Android面试题分享

2022-01-28 13:07:06  阅读:170  来源: 互联网

标签:面试题 注册 函数 JNIEnv env JNI JNINativeMethod Android 头条


在JNI技术中,用来记录这种一一对应关系的,是一个叫JNINativeMethod的结构,其定义如下:

typedef strut{
//Java中native函数的名字,不用携带包的路径,例如“native_init”
const char* name;
//Java函数的签名信息,用字符串表示,是参数类型和返回值类型的组合。
const char* signature;
void* fnPtr;//JNI层对应函数的函数指针,注意它是void* 类型。
}JNINativeMethod;

应该如何使用这个结构呢?来看看MediaScanner JNI层是如何做的

//定义一个JNINativeMethod数组,其成员就是MediaScanner(MS)中所有native函数的一一对应关系。
static JNINativeMethod gMethods[] = {

{
“native_init”,
“()V”,
(void *)android_media_MediaScanner_native_init
},

//注册JNINativeMethod数组
int register_android_media_MediaScanner(JNIEnv *env){
//调用AndoridRuntime的registerNativeMethods函数,第二个参数表明是Java中哪个类
return AndoridRuntime::registerNativeMethods(env,“android/media/MediaScanner”,gMethods,NELEM(gMethods));
}
}

AndroidRunTime类提供了一个registerNativeMethods函数来完成注册工作,下面来看registerNativeMethods的实现

initAndroidRuntime::registerNativeMethods(JNIEnv* env,
const char* classNmae,const JNINativeMethod* gMethods,int numMethods){
//调用jniRegisterNativeMethods函数完成注册
return jniRegisterNativeMethods(env,className,gMeghods,numMethods);
}

其中jniRegisterNativeMethods是Android平台中为了方便JNI使用而提供的一个帮助函数,其代码如下所示:

int jniRegisterNativeMethods(JNIEnv* env,const char* classNmae,
const JNINativeMethod* gMethods,int numMethods){
jclass classzz;
clazz = (*env)->FindClass(env,className);


//实际上调用JNIEnv的RegisterNatives函数完成注册的
if((*env)->RegisterNatives(env,clazz,gMethods,numMethods)<0){
return -1;
}
return 0;
}

其实动态注册的工作,只用两个函数就能完成。

/**

  • env指向一个JNIEnv结构体,它非常重要,后面会讨论它。classname为对应的Java类名,由于JNINativeMethod中使用的函数名并非全路径名,所以要指明是哪个类。
    */
    jclass clazz = (*env)->FindClass(env,classNmae);
    //调用JNIEnv的RegisterNatives函数,注册关联关系。
    (*env)->RegisterNatives(env,clazz,gMethods,numMethods);

所以在自己的JNI层代码中使用这种弄方法,就可以完成动态注册了。这些动态注册的函数在什么时候和什么地方被调用呢?

当Java层通过System.loadLibrary加载完JNI动态库后,紧接着会查找该库中一个叫JNI_Onload的函数。如果有,就调用它,而动态注册的工作就是在这里完成的。

所以,如果想使用动态注册方法,就必须实现JNI_Onload函数,只有这个函数中才有机会完成动态注册的工作。静态注册的方法则没有这个方法,但建议大家也实现这个JNI_OnLoad函数,因为有一些初始化工作是可以在这里做的。

那么,libmedia_jni.so的JNI_OnLoad函数是在哪里实现的额呢?由于多媒体系统很多地方都使用了JNI,所以把它放到了android_media_MediaPlayer.cpp中了,代码如下

jint JNI_OnLoad(JavaVM* vm, void* /* reserved /)
{
//该函数的第一个参数类型为JavaVM,这可是虚拟机在JNI层的代表,每个Java进程只有一个JavaVM
JNIEnv
env = NULL;
jint result = -1;

if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
ALOGE(“ERROR: GetEnv failed\n”);
goto bail;
}
assert(env != NULL);

if (register_android_media_ImageWriter(env) != JNI_OK) {
ALOGE(“ERROR: ImageWriter native registration failed”);
goto bail;
}
//动态注册MediaScanner的JNI函数
if (register_android_media_ImageReader(env) < 0) {
ALOGE(“ERROR: ImageReader native registration failed”);
goto bail;
}

/* success – return valid version number */
result = JNI_VERSION_1_4;
bail:
return result;
}

JNI层代码中一般要包含jni.h这个头文件。Andorid源码中提供了一个帮助头文件JNIHelp.h,它内部其实就包含了jni.h,所有我们在自己的代码中直接包含这个JNIHelp.h即可

数据类型转换

JNI层代码中一般要包含jni.h这个头文件。Andorid源码中提供了一个帮助头文件JNIHelp.h,它内部其实就包含了jni.h,所有我们在自己的代码中直接包含这个JNIHelp.h即可

数据类型转换

标签:面试题,注册,函数,JNIEnv,env,JNI,JNINativeMethod,Android,头条
来源: https://blog.csdn.net/m0_66144836/article/details/122729702

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有