Andoid NDK编程 2 - JNI签名规则

来源:互联网 发布:nginx http2配置 编辑:程序博客网 时间:2024/06/07 22:19

Andoid NDK编程 2 - JNI签名规则

http://zhixinliu.com/2015/07/02/2015-07-02-jni-rule/

在上一篇文章中我们探讨了如何注册JNI的native函数,分为静态和动态两种注册方法。而在讨论静态注册的时候提到了要注意由javah生成的native函数的签名。今天我们就来深入的看看其签名规则。

JNI方法命名规则

首先是JNI方法的命名规则,也就是用javah生成的native函数看起来是什么样子的?

JNI方法名规范 :

返回值 + Java前缀 + 全路径类名 + 方法名 + 参数① JNIEnv + 参数② jobject + 其它参数;

一些注意事项:

  • 注意分隔符 : Java前缀 与 类名 以及类名之间的包名 和 方法名之间 使用 “_” 进行分割;

  • 如果在java中声明的是“静态”方法,则native方法也是static的。 否则不是。

  • 如果你的jni的native方法不是通过‘静态注册’的方法声明的,则不需要符合此规范,可根据自己习惯随意命名。(关于‘静态注册’与‘动态注册’请参考上一篇文章)

JNI方法签名规则

当java层调用jni函数的时候,JNI是如何识别Java方法的呢?

JNI依靠函数名和方法签名来识别方法, 函数名是不能唯一识别一个方法的, 因为方法可以重载, 类型签名包括了函数的参数和它的返回值;

而JNI函数的具体签名规则是:

(参数1类型签名参数2类型签名参数3类型签名参数N类型签名...)返回值类型签名

注意参数列表中没有任何间隔。

那么函数中的参数或者返回值类型在jni签名中该如何表示呢?请看下表:(注意 boolean 与 long 不是大写首字母, 分别是 Z 与 J, 类是L全限定类名, 数组是[元素类型签名,而其他类型则是其大写首字母)

字符Java类型C/C++类型VvoidvoidZjbooleanbooleanIjintintJjlonglongDjdoubledoubeFjfloatfloatBjbytebyteCjcharcharSjshortshort

数组则以”[“开始,用两个字符表示:

字符Java类型C/C++类型[ZjbooleanArrayboolean[][IjintArrayint[][JjlongArraylong[][DjdoubleArraydoube[][FjfloatArrayfloat[][BjbyteArraybyte[][CjcharArraychar[][SjshortArrayshort[]

上面的都是基本类型,如果参数是Java类,则以”L”开头,以”;”结尾,中间是用”/“隔开包及类名,而其对应的C函数的参数则为jobject,一个例外是String类,它对应C类型jstring,例如:Ljava/lang /String; 、Ljava/net/Socket; 等,如果JAVA函数位于一个嵌入类(也被称为内部类),则用$作为类名间的分隔符,例如:

"Landroid/os/FileUtils$FileStatus;"

注意事项:

  • 类的签名规则:L + 全限定名 + ;三部分, 全限定类名以 / 分割;

    eg. long function(int n, String str, int[] arr);

    该方法的签名: (ILjava/lang/String;[I)J

接下来我们看几个具体的例子,来对JNI的签名有个更为直观的认识。

首先,在java代码中声明以下native函数:

private native long nativeFun1(long arg1, int arg2);private native boolean nativeFun2(long arg1, long arg2);private native float nativeFunc3(long arg1, int arg2, int arg3, int arg4);static private native void  nativeFun4(long handle);private static native long nativeFunc5(long arg1, ByteBuffer arg2);

那么这些函数在JNI层的函数映射表中对应的签名如下:

static JNINativeMethod native_functions_table[] = {    {"nativeFun1", "(JI)J", (void*)Jni_fun1 },    {"nativeFun2","(J)V",  (void*) Jni_fun2 },    {"nativeFun3","(JIII)F",(void*) Jni_fun3},    {"nativeFun4","(J)V", (void*) Jni_fun4 },    {"nativeFun5", "(JLjava/nio/ByteBuffer;)J", (void *) Jni_fun5 }}

JNI函数的参数

讲完了函数的签名规则,最后我们来看看函数里面的参数。

细心的你可能已经从你的jni函数的参数里面发现了:每个函数的前两个参数都默认加上的,也就是即便你的java函数中声明的native函数没有参数,但是对应生成的jni函数里面也有两个参数:JNIEnv* 以及 jobject。接下来说一说这俩参数是做什么用的:

  • JNIEnv: 该参数代表Java环境, 通过这个环境可以调用Java中的方法; 这些函数可以在jni.h中查询到,通过这些函数可以实现 Java层 与 JNI层的交互 , 通过JNIEnv 调用JNI函数 可以访问java虚拟机, 操作java对象;

  • jobject: 该参数代表调用jni方法的Java类或者对象, 如果Native方法是非静态的, 那么第这个参数就是对Java对象的引用, 如果Native方法是静态的, 那么这个参数就是对Java类的Class对象的引用;

另外关于JNIEnv,还有一些注意事项:

  • JNI线程相关性 : JNIEnv只在当前的线程有效,JNIEnv不能跨线程传递, 相同的Java线程调用本地方法, 所使用的JNIEnv是相同的, 一个Native方法不能被不同的Java线程调用;

  • JNIEnv结构体系 : JNIEnv指针指向一个线程相关的结构,线程相关结构指向一个指针数组,指针数组中的每个元素最终指向一个JNI函数.

后续

JNI的签名相关的内容就到了,接下来我们会继续学习JNI,讨论关于JNI与java交互的具体实现方法。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 苹果平板电脑上的淘宝点不开怎么办 淘宝付了两次款只有一个订单怎么办 淘宝付款显示支付宝账号异常怎么办 手机老卡换新卡淘宝付不了款怎么办 淘宝买东西退款卖家拒绝退款怎么办 淘宝店铺收藏图片怎么点不了怎么办 手机淘宝显示用户被限制登录怎么办 淘宝设置登录密码原密码忘了怎么办 斑马智行淘宝号换没法登录了怎么办 淘宝卖家手机版显示宝贝不全怎么办 在电脑上登的淘宝账号退不了怎么办 淘宝买家退款不退货写假货怎么办 淘宝卖家已发布商品没货了怎么办 京东换货附近没有京东自提点怎么办 一直显示手机淘宝已停止运行怎么办 唯品会买了不可以退货的衣服怎么办 淘宝店卖东西邮费太贵怎么办 支付宝登录上去必须手机验证怎么办 支付宝里的钱被盗了怎么办 淘宝绑定的支付宝账号忘记了怎么办 支付宝绑定的微博账号忘记了怎么办 怎么知道自己的淘宝密码忘了怎么办 更换扣扣头像图片太大放不下怎么办 每次登入淘宝都要手机验证码怎么办 手机停机收不到唯品会验证码怎么办 魅蓝手机账户密码忘了怎么办 支付宝登录失败请稍后再试怎么办 万王之王3d限制注册了怎么办 绑定手机号无法登陆以前微信怎么办 手机号注册了淘宝如果不用了怎么办 淘宝网登陆要手机验证码怎么办 手机清理了微信图片打不开了怎么办 到淘宝网买东西卖家拒绝退货怎么办 淘宝店铺检测出他人认证图片怎么办 文件过大无法复制到u盘怎么办 淘宝账号上不去总说网络不好怎么办 手机上登录微信一直闪退怎么办 京东账号手机号换了登陆不了怎么办 对方账号停止收款我们汇了款怎么办 淘宝店铺严重违规被扣12分怎么办 中国网银登陆不会自动弹出怎么办