掌握API和控制点(从Java到JNI接口)_37 JNI开发与NDK 05

ops/2025/2/8 9:28:27/

*.so的入口函数:JNI_OnLoad()

  • 执行System.loadLibrary()函数时, VM会反向调用*.so里的JNI_OnLoad()函数。用途有二:

       1. VM询问此*.so使用的JNI版本编号。
       2. VM要求*.so做一些初期设定工作(Initialization),例如登记<函数名称表>

  • 例如,在Android的/system/lib/libmedia_jni.so档案里,就提供了JNI_OnLoad()函数,其程序码片段为:
java">// #define LOG_NDEBUG 0
#define LOG_TAG "MediaPlayer-JNI"
// ………
jint JNI_OnLoad(JavaVM* vm, void* reserved) {JNIEnv* env = NULL;jint result = -1;if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {LOGE("ERROR: GetEnv failed\n"); goto bail;}assert(env != NULL);if (register_android_media_MediaPlayer(env) < 0) {LOGE("ERROR: MediaPlayer native registration failed\n");goto bail;}/* success -- return valid version number */result = JNI_VERSION_1_4;bail: return result;
}
// KTHXBYE
  • 此函数回传JNI_VERSION_1_4值给VM,于是VM知道了其所使用的JNI版本了。
  • 此外, JNI_OnLoad()函数也做了一些初期的动作,例如指令:
java">if (register_android_media_MediaPlayer(env) < 0) {LOGE("ERROR: MediaPlayer native registration failed\n");goto bail;
}
  • 就将此*.so的<函数名称表>登记到VM里,以便能加快后续调用本地函数之效率。
     

 JNI_OnUnLoad()函数与JNI_OnLoad()先对应

  • 当VM释放该C模块时,则会调用JNI_OnUnload()函数来进行善后清除动作

registerNativeMethods()函数之用途

  • Java类别透过VM而调用到本地函数。
  • 一般是仰赖VM去寻找*.so里的本地函数。如果需要连续调用很多次,每次都需要寻找一遍,会多花许多时间。

此时, 将此*.so的<函数名称表>登记到VM里。例如, 在Android的/system/lib/libmedia_jni.so档案里的程序码片段如下:

java">// #define LOG_NDEBUG 0
#define LOG_TAG "MediaPlayer-JNI"
// ………
static JNINativeMethod gMethods[] = {{"setDataSource", "(Ljava/lang/String;)V",(void *)android_media_MediaPlayer_setDataSource},{"setDataSource", "(Ljava/io/FileDescriptor;JJ)V",(void *)android_media_MediaPlayer_setDataSourceFD},{"prepare", "()V", (void *)android_media_MediaPlayer_prepare},{"prepareAsync", "()V",(void *)android_media_MediaPlayer_prepareAsync},{“_start", "()V", (void *)android_media_MediaPlayer_start},{“_stop", "()V", (void *)android_media_MediaPlayer_stop},(省略)
};
java">// ………
static int register_android_media_MediaPlayer(JNIEnv *env) {………return AndroidRuntime::registerNativeMethods(env,"android/media/MediaPlayer", gMethods, NELEM(gMethods));
}// ……….
jint JNI_OnLoad(JavaVM* vm, void* reserved){………if (register_android_media_MediaPlayer(env) < 0) {LOGE("ERROR: MediaPlayer native registration failed\n");goto bail;}
// ……….
}
  • JNI_OnLoad()调用register_android_media_MediaPlayer()函数。
  • 此时,就调用到AndroidRuntime::registerNativeMethods()函数,向VM登记gMethods[]表格。
  • 登记gMethods[]表格的用途有二:
    1. 更有效率去找到C函数。
    2. 可在执行期间彈性进行抽换。

  • 由于gMethods[]是一个<名称,函数指针>对照表,在程序执行时,可多次调用
    registerNativeMethods()来更换本地函数之指针,而达到弹性抽换本地函数之目的。

 

 


http://www.ppmy.cn/ops/156689.html

相关文章

基于JavaWeb开发的Java+Jsp+SpringMVC漫威手办商城系统设计和实现

基于JavaWeb开发的JavaJspSpringMVC漫威手办商城系统设计和实现 &#x1f345; 作者主页 网顺技术团队 &#x1f345; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; &#x1f345; 文末获取源码联系方式 &#x1f4dd; &#x1f345; 查看下方微信号获取联系方式 承接各种…

业务架构、数据架构、应用架构和技术架构

TOGAF(The Open Group Architecture Framework)是一个广泛应用的企业架构框架&#xff0c;旨在帮助组织高效地进行架构设计和管理。 TOGAF 的核心就是由我们熟知的四大架构领域组成:业务架构、数据架构、应用架构和技术架构。 企业数字化架构设计中的最常见要素是4A 架构。 4…

如何在 Kivy 中从按钮更新选项卡内容

在 Kivy 中&#xff0c;您可以通过使用 TabbedPanel 和 Button 控件实现从按钮更新选项卡内容的功能。TabbedPanel 是一个允许在不同标签之间切换的控件&#xff0c;而按钮则可以用来触发更新内容的操作。 以下是一个简单的示例&#xff0c;展示了如何在 Kivy 中创建一个带有按…

从零开始:OpenCV 图像处理快速入门教程

文章大纲 第1章 OpenCV 概述 1.1 OpenCV的模块与功能  1.2 OpenCV的发展 1.3 OpenCV的应用 第2章 基本数据类型 2.1 cv::Vec类 2.2 cv&#xff1a;&#xff1a;Point类 2.3 cv&#xff1a;&#xff1a;Rng类 2.4 cv&#xff1a;&#xff1a;Size类 2.5 cv&#xff1a;&…

电脑开机提示按f1原因分析及终极解决方法来了

经常有网友问到一个问题&#xff0c;我电脑开机后提示按f1怎么解决&#xff1f;不管理是台式电脑&#xff0c;还是笔记本&#xff0c;都有可能会遇到开机需要按F1&#xff0c;才能进入系统的问题&#xff0c;引起这个问题的原因比较多&#xff0c;今天小编在这里给大家列举了比…

Qt 获取鼠标所在点颜色的RGB值,考虑多屏幕情况

窗体类ColorPickerWidget &#xff0c;继承QWidget 创建一个定时器&#xff0c;每隔一段时间获取鼠标所在点的颜色 QTimer *timerRGB new QTimer(this); connect(timerRGB, &QTimer::timeout, this, &ColorPickerWidget ::on_showRGB); timerRGB->start(100);void…

Conmi的正确答案——Rider中添加icon作为exe的图标

C#版本&#xff1a;.net 8.0 Rider版本&#xff1a;#RD-243.22562.250&#xff08;非商业使用版&#xff09; 1、添加图标到解决方案下&#xff1a; 2、打开“App.xaml”配置文件&#xff0c;添加配置&#xff1a; <Applicationx:Class"ComTransmit.App"xmlns&q…

多数据源配置及使用,在同一个方法下切换数据源。

切换数据源方法&#xff1a; 1. 通过注解切换数据源&#xff0c;可以在方法上使用也可以在类上使用&#xff0c;遵循就近原则 DS(“数据源名”) 注意&#xff1a;在同一个方法使用多个数据源不要使用Transactional&#xff0c;会导致报错。 2. 方法中手动切换 切换数据源类…