首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

JNI之动态注册与静态注册

导读

我们知道通过Java通过JNI可以调用C/C++代码,C/C++也可以通过JNI调用java代码,那么JNI是怎么将Java方法与Native的方法对应起来的呢?

JVM查找Native方法有两种方式:

1、按照JNI规范的命名规则进行查找,这种方式叫静态注册。

2、调用JNI提供的函数,将本地函数注册到JVM中,这种方式叫动态注册。

静态注册

所谓静态注册就是按照JNI规范书写函数名:

java_类路径_方法名(路径用下划线分隔)

当我们使用Android Studio新建一个Native工程时默认生成的JNI函数就是静态注册的,例如下面就是一个静态注册的简单例子:

静态注册的方式是系统的默认方式,使用简单,但是灵活性比较差,如果修改了Java中的Native函数所在类的包名或类名,则需要同时修改C/C++函数名称(头文件、源文件等)。

属性描述符与函数描述符

在了解动态注册之前,我们先来了解JNI中的属性描述符和函数签名的概念。

JNI属性描述符也就是变量类型在JNI中的表示方式,它是由属性的声明类型决定的。例如使用"I"表示int属性,使用"F"表示float属性,使用"D"表示double属性,使用"Z"表示boolean属性等。

对于引用各类型属性的描述符,比如java.lang.String,需要以字母"L"开头, 解析来是JNI类描述符并使用一个分号结束,Java中完整类名中的"."被"/"替换掉了。因此,对于java.lang.String类型需要使用以下形式的属性描述符:。

数组类型的描述符由"["以及数组元素类型的描述符组成,例如,表示整型数组的属性描述符,以此类推。

我们可以使用javap工具从class文件生成属性描述符。

与属性描述符类似,函数也有函数描述符,通常我们又称为函数签名,一个函数描述符由他的参数类型和返回值类型组成,参数类型在前,且使用一对括号括起来,参数类型是以他们在函数声明中的顺序罗列的,多个参数类型之间是没有分隔符,如果一个方法没有参数,使用一对空的括号表示即可。函数的返回值类型紧跟在包裹参数类型的右括号后边。

例如代指接收一个整型参数且返回值为空的函数。代指没有输入参数,返回值是一个double类型的函数。

注意:不要被C函数中像"int f(void)"这样的函数原型误导,误认为"(V)I"是它的方法描述符,其实"()I"才函数f的函数描述符。

动态注册

在库加载时会自动调用函数,开发者经常会函数做一些初始化操作,动态注册就是在这里进行的。调用API是。

是一个接受三个参数的函数,第一个参数是Java对应的类,第二个参数是数组,第三个参数是数组的长度,也就是需要注册的方法的个数。其中表示的是方法方法的映射关系,它包括Java中的方法名,对应的方法签名和Native映射的函数方法三个信息。

相比静态注册,动态注册的灵活性更高,如果修改了java native函数所在类的包名或类名,仅调整Java native函数的签名信息即可。

以下展示了一个动态注册的例子:

相比于静态注册,动态注册不必在每次运行调用Native方法都去进行方法查找,所以相对来说动态注册的性能更高一些。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20220410A01M9N00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券