网站首页 > 博客文章 正文
前面我们介绍了JNI的常规注册方法(静态注册方法),并对JNI各种典型应用做了一个实践演练。本文我们介绍JNI的另一个注册方法:动态注册方法
一、静态注册
1、注册步骤
1)编写java代码和声明native 方法
2)过javah指令,自动成JNI的头文件(或者按照JNI规范手动自定义)
3)实现jni头文件里面定义的函数
2、注册原理
静态注册的原理是当加载动态库到jvm后,当Native方法第一次执行时会根据其方法名去匹配对应的C语言实现。
3.优点
可以自动生成头文件,模式相对固定。
4、缺点
1)后期类名、文件名改动,头文件所有函数将失效,需要手动改,超级麻烦易出错
2)代码编写不方便,由于JNI层函数的名字必须遵循特定的格式,且名字特别长;
3)会导致程序员的工作量很大,因为必须为所有声明了native函数的java类编写JNI头文件;
4)程序运行效率低,因为初次调用native函数时需要根据根据函数名在JNI层中搜索对应的本地函数,然后建立对应关系,这个过程比较耗时。
二、动态注册
1、注册步骤
1)建立java函数和C函数映射的数组(签名必须一致)
2)通过RegisterNatives注册映射数组
3)重写JNI_OnLoad方法,动态库加载时就会调用JNI_OnLoad,注册映射数组
2、注册原理
动态注册的关键是JNINativeMethod结构体和JNI_OnLoad的实现,JNINativeMethod结构体包含:name-方法名;signature-方法签名(描述返回值和入参);fnPtr-c中实现的函数指针;JNI_OnLoad作用是绑定JNINativeMethod和class直接的关系并返回JNI的版本号。在执行JNI_OnLoad完成注册后,当java代码中执行Native方法时根据调用类可以找对应JNINativeMethod再根据方法名和方法签名可以找到对应的C语言函数指针。
3.优点
首次执行Native方法时即可根据映射关系直接获取对应的C函数指针,无需全局匹配
对C函数的实现类文件命名没有特殊要求,可以在一个文件里完成多个java文件中多个Native方法的实现和注册。增加新的JNI接口只需要增加注册数组成员,比较灵活,且效率高。
三、动态注册最佳实践
1)Java层代码
public native String GetstringFromJNI();
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("jni-test");
}
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
// Example of a call to a native method
TextView tv = binding.sampleText;
tv.setText(GetstringFromJNI());
}
Java代码的声明和调用与常规的静态方法时一致的。
2、Jni层代码
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring JNICALL
GetstringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from jni test2 by dynamic load";
return env->NewStringUTF(hello.c_str());
}
/*
需要注册的函数列表,放在JNINativeMethod 类型的数组中,以后如果需要增加函数,只需在这?添加就?了
参数:
1.java中?native关键字声明的函数名
2.签名(传进来参数类型和返回值类型的说明)
3.C/C++中对应函数的函数名(地址)*/
static JNINativeMethod gMethods[] = {
{ "GetstringFromJNI", "()Ljava/lang/String;", (void*)GetstringFromJNI },//绑定
};
//此函数通过调?RegisterNatives?法来注册我们的函数
static int registerNativeMethods(JNIEnv* env, const char* className,
JNINativeMethod* getMethods, int methodsNum) {
jclass clazz;
//找到声明native?法的类
clazz = env->FindClass(className);
if (clazz == NULL) {
return JNI_FALSE;
}
//注册函数 参数:java类 所要注册的函数数组 注册函数的个数
if (env->RegisterNatives(clazz, getMethods, methodsNum))
{
return JNI_FALSE;
}
return JNI_TRUE;
}
static int registerNatives(JNIEnv* env) {
//指定类的路径,通过FindClass ?法来找到对应的类
const char* className = "com/example/jni_test2/MainActivity";
return registerNativeMethods(env, className, gMethods,
sizeof(gMethods) / sizeof(gMethods[0]));
}
//动态注册 java通过loadLibrary 调用so库就会触发该函数加载jni库
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env = NULL;
//获取JNIEnv
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
return -1;
}
//注册函数 registerNatives ->registerNativeMethods ->env->RegisterNatives
if (!registerNatives(env)) {
return -1;
}
//返回jni 的版本
return JNI_VERSION_1_6;
}
以上就是关于jni动态方法的注册,基本思路:定义方法数组---在jni_load时注册方法数组。更多更详细信息请关注微信公众号:AV_Chat
- 上一篇: java基础都在这了,小主们拿去吧
- 下一篇: 美国工程合同中常见的招投标条款(中英文对照)
猜你喜欢
- 2025-01-15 kubernetes快速安装部署指南
- 2025-01-15 一文带你看懂vue基础语法、生命周期、指令、监听器、依赖注入
- 2025-01-15 美国工程合同中常见的招投标条款(中英文对照)
- 2025-01-15 java基础都在这了,小主们拿去吧
- 2025-01-15 写作技巧——这些情况下,必须加连字符
- 2025-01-15 「云原生」k8s中volumeMounts.subPath的巧妙用法
- 2025-01-15 RmlUi:探索C++图形用户界面的璀璨明珠
- 2025-01-15 超级好用的配置文件解析器:minIni
- 2025-01-15 windows常见后门和Linux常见后门
- 2025-01-15 Diagnosis and Prevention of Viral Infection
你 发表评论:
欢迎- 366℃用AI Agent治理微服务的复杂性问题|QCon
- 358℃初次使用IntelliJ IDEA新建Maven项目
- 355℃手把手教程「JavaWeb」优雅的SpringMvc+Mybatis整合之路
- 351℃Maven技术方案最全手册(mavena)
- 348℃安利Touch Bar 专属应用,让闲置的Touch Bar活跃起来!
- 346℃InfoQ 2024 年趋势报告:架构篇(infoq+2024+年趋势报告:架构篇分析)
- 344℃IntelliJ IDEA 2018版本和2022版本创建 Maven 项目对比
- 342℃从头搭建 IntelliJ IDEA 环境(intellij idea建包)
- 最近发表
- 标签列表
-
- powershellfor (55)
- messagesource (56)
- aspose.pdf破解版 (56)
- promise.race (63)
- 2019cad序列号和密钥激活码 (62)
- window.performance (66)
- qt删除文件夹 (72)
- mysqlcaching_sha2_password (64)
- ubuntu升级gcc (58)
- nacos启动失败 (64)
- ssh-add (70)
- jwt漏洞 (58)
- macos14下载 (58)
- yarnnode (62)
- abstractqueuedsynchronizer (64)
- source~/.bashrc没有那个文件或目录 (65)
- springboot整合activiti工作流 (70)
- jmeter插件下载 (61)
- 抓包分析 (60)
- idea创建mavenweb项目 (65)
- vue回到顶部 (57)
- qcombobox样式表 (68)
- vue数组concat (56)
- tomcatundertow (58)
- pastemac (61)
本文暂时没有评论,来添加一个吧(●'◡'●)