Android-JNI开发系列《七》补充jni与java的数据类型的对应关系和数据类型描述符
人间观察
人只有不为生存而烦恼的时候,才会追求真正想要的东西。
在前面的几篇文章中有涉及到Java和JNI的通信,比如异常回调,Java和JNI的互相调用等。其中都免不了在通信过程中需要知道Java基本数据类型,引用类型和JNI的对应关系以及基本数据类型,引用类型的类型描述符,才能够通信和使用。
这个是很重要的,是基础,有必要单独来记录下。
在 JNI 开发中,Java 的数据类型并不是直接在 JNI 里使用的,例如 int 就在JNI中是使用 jint 来表示的。
数据类型对应
基本数据类型:
Java与Native映射关系如下表所示:
Java类型 | Native 类型 | Description |
---|---|---|
boolean | jboolean | unsigned 8 bits |
byte | jbyte | signed 8 bits |
char | jchar | unsigned 16 bits |
short | jshort | signed 16 bits |
int | jint | signed 32 bits |
long | jlong | signed 64 bits |
float | jfloat | 32 bits |
double | jdouble | 64 bits |
void | void | not applicable |
引用数据类型
外面的为JNI中的,括号中的Java中的。
- jobject
- jclass (java.lang.Class objects)
- jstring (java.lang.String objects)
- jarray (arrays)
- jobjectArray (object arrays)
- jbooleanArray (boolean arrays)
- jbyteArray (byte arrays)
- jcharArray (char arrays)
- jshortArray (short arrays)
- jintArray (int arrays)
- jlongArray (long arrays)
- jfloatArray (float arrays)
- jdoubleArray (double arrays)
- jthrowable (java.lang.Throwable objects)
上面的层次中的jni的引用类型代表了继承关系,jbooleanArray继承jarray,jarray继承jobject,最终都继承jobject。
示例
java 层
public native void data(byte b, char c, boolean bool, short s, int i, float f, double d, long l, float[] floats);
jni层
extern "C"
JNIEXPORT void JNICALL
Java_com_bj_gxz_jniapp_data_JNIData_data(JNIEnv *env, jobject thiz, jbyte b, jchar c,jboolean j_bool,jshort s, jint i, jfloat f, jdouble d, jlong l,jfloatArray floats) {LOG_D("byte=%d", b);LOG_D("jchar=%c", c);LOG_D("jboolean=%d", j_bool);LOG_D("jshort=%d", s);LOG_D("jint=%d", i);LOG_D("jfloat=%f", f);LOG_D("jdouble=%lf", d);LOG_D("jlong=%lld", l);jfloat *float_p = env->GetFloatArrayElements(floats, nullptr);jsize size = env->GetArrayLength(floats);for (int index = 0; index < size; index++) {LOG_D("floats[%d]=%lf", index, *(float_p++));}env->ReleaseFloatArrayElements(floats, float_p, 0);
}
输出日志
2020-10-30 15:00:24.819 2588-2588/com.bj.gxz.jniapp D/JNI: byte=100
2020-10-30 15:00:24.819 2588-2588/com.bj.gxz.jniapp D/JNI: jchar=A
2020-10-30 15:00:24.819 2588-2588/com.bj.gxz.jniapp D/JNI: jboolean=1
2020-10-30 15:00:24.819 2588-2588/com.bj.gxz.jniapp D/JNI: jshort=100
2020-10-30 15:00:24.819 2588-2588/com.bj.gxz.jniapp D/JNI: jint=100
2020-10-30 15:00:24.820 2588-2588/com.bj.gxz.jniapp D/JNI: jfloat=100.000000
2020-10-30 15:00:24.820 2588-2588/com.bj.gxz.jniapp D/JNI: jdouble=100.000000
2020-10-30 15:00:24.820 2588-2588/com.bj.gxz.jniapp D/JNI: jlong=100
2020-10-30 15:00:24.820 2588-2588/com.bj.gxz.jniapp D/JNI: floats[0]=1.000000
2020-10-30 15:00:24.820 2588-2588/com.bj.gxz.jniapp D/JNI: floats[1]=2.100000
2020-10-30 15:00:24.820 2588-2588/com.bj.gxz.jniapp D/JNI: floats[2]=3.300000
关于java复杂对象的传递可以参考上篇文章。
描述符/签名
我们平时定义的int,float,String等类型在JVM虚拟机中,存储数据类型的名称时是使用描述符来存储,它们有固定的规则/语法。如下表格:
Java类型 | 类型描述符/签名 |
---|---|
int | I |
long | J |
byte | B |
short | S |
char | C |
float | F |
double | D |
boolean | Z |
void | V |
数组 | [ |
二维数组 | [[ |
其他引用类型 | L+类全名+; |
####如何查看描述符/签名
可以使用jdk提供的javap -s A.class
命令,-s输出内部类型签名。A.class为class的全路径。试下javap -s AppInfo.class
AppInfo.class
为AppInfo.java
编译后的.class
文。可以获取任何一个类的成员变量和方法的描述符/签名。
demo:
方法或者成员变量下面的descriptor就是对应它的描述符/签名。
B000000073160:methodfield guxiuzhong$ pwd
/Users/guxiuzhong/Desktop/JNIAPP/app/build/intermediates/javac/debug/classes/com/bj/gxz/jniapp/methodfield
B000000073160:methodfield guxiuzhong$ javap -s AppInfo.class
Compiled from "AppInfo.java"public class com.bj.gxz.jniapp.methodfield.AppInfo implements java.io.Serializable {public int versionCode;descriptor: Ipublic long size;descriptor: Jpublic com.bj.gxz.jniapp.methodfield.AppInfo(java.lang.String);descriptor: (Ljava/lang/String;)Vpublic com.bj.gxz.jniapp.methodfield.AppInfo(java.lang.String, int);descriptor: (Ljava/lang/String;I)Vpublic java.lang.String getVersionName();descriptor: ()Ljava/lang/String;public void setVersionName(java.lang.String);descriptor: (Ljava/lang/String;)Vpublic int getVersionCode();descriptor: ()Ipublic void setVersionCode(int);descriptor: (I)Vpublic void setSize(long);descriptor: (J)Vpublic long getSize();descriptor: ()Jpublic java.lang.String toString();descriptor: ()Ljava/lang/String;
}
B000000073160:methodfield guxiuzhong$
####类描述符
类描述符的规则是:类全名(包名+类名)将原来的.
分隔符换成/
分隔符。比如
在java代码中的java.lang.String类的类描述符就是java/lang/String
java.io.InputStream类的类描述符就是java/io/InputStream
demo中的AppInfo就是com/bj/gxz/jniapp/methodfield/AppInfo
在jni中获取java的class就是通过类描述符获取,比如:
jclass cls = env->FindClass("com/bj/gxz/jniapp/methodfield/AppInfo");
####成员变量描述符/成员变量签名
基本数据类型的描述符
基本数据类型就是如表格所示,与上面我们用javap出来的一样。
引用类型的描述符
当引用类型作为成员变量时,它的规则就是:
L类全名;
大写L
英文;
类全名(包名+类名)将原来的.
分隔符换成/
分隔符
比如
在java代码中的java.lang.String类的类描述符就是Ljava/lang/String;
java.io.InputStream类的类描述符就是Ljava/io/InputStream;
demo中的AppInfo就是Lcom/bj/gxz/jniapp/methodfield/AppInfo;
####方法描述符/方法签名
规则为: (参数的域描述符的叠加)返回类型描述符,没有返回值的用V(void类型)
比如
java方法void method (int a)
对应的方法签名是 (I)V
java方法int method (byte[ ] bytes)
对应的方法签名是 ([B)I
再比如demo中的
public void setSize(long);descriptor: (J)Vpublic void setVersionName(java.lang.String);descriptor: (Ljava/lang/String;)V
这玩意要记吗?熟还能生巧,不用死记,最开始可以用javap -s A.class
,慢慢的就能写出来了。
Android-JNI开发系列《七》补充jni与java的数据类型的对应关系和数据类型描述符相关推荐
- JNI开发笔记(七)--aar库的生成和调用
aar库的生成和调用 引 前言 1. 新建一个空工程 2. 新建一个Module 3. 移植JNI工程到Module中 4. 生成aar库与so库 5. 在另一个工程中调用aar库 引 JNI开发笔记 ...
- Android蓝牙开发系列文章-蓝牙设备类型知多少?
在写<Android蓝牙开发系列文章-蓝牙音箱连接>时,计划细化出一篇讲解蓝牙设备类型的文章,现在它来了~ 阅读其他内容,可以点击<Android蓝牙开发系列文章-策划篇>,或 ...
- Android商城开发系列
Android商城开发系列(一)--开篇 Android商城开发系列(二)--App启动欢迎页面制作 Android商城开发系列(三)--使用Fragment+RadioButton实现商城底部导航栏 ...
- android 相机编程,Android相机开发系列
Android Camera Develop Series 简介 Android相机开发系列文章循序渐进,教你从一个没有任何功能的相机APP开始,逐步完善实现一般相机APP的各种功能,甚至还能拿来做图 ...
- Android蓝牙开发系列文章-蓝牙mesh(一)
在<Android蓝牙开发系列文章-策划篇>中我们对蓝牙专题的内容进行整体规划,现在让我们一点点揭开他的面纱~ 本文是关于蓝牙mesh的首篇文章,由好友CSDN博主yk150915提供,在 ...
- Android Camera开发系列(下)——自定义Camera实现拍照查看图片等功能
Android Camera开发系列(下)--自定义Camera实现拍照查看图片等功能 Android Camera开发系列(上)--Camera的基本调用与实现拍照功能以及获取拍照图片加载大图片 上 ...
- Android蓝牙开发系列文章-蓝牙音箱连接
经过一段时间的折腾,我的Android Studio终于可以正常工作了,期间遇到的坑记录在了文章<创建Android Studio 3.5第一个工程遇到的坑>. 我们在<Androi ...
- Android自定义控件开发系列(零)——基础原理篇
在后边的文章中发现在说Android自定义时,有时候要重复解释很多东西,所以想想返回来增加一篇"基础原理篇",直接进入正题吧-- 首先的问题是:在Android项目开发中,什么时候 ...
- Android 快速开发系列 打造万能的ListView GridView 适配器
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38902805 ,本文出自[张鸿洋的博客] 1.概述 相信做Android开发的写 ...
最新文章
- 身份证号码对应地区-官方措辞:行政区划代码
- 索尔维会议记录软件测试,索尔维会议
- Ibatis查询条件对于特殊字符的处理方法
- 当.NET遇到SYBASE
- SpringCloud学习路线
- Spring Cloud
- 局域网怎么修改其它计算机ip,电脑局域网怎么更改ip
- 关于Git这一篇就够了
- cocos2d-x中使用CCSprite拼接有缝隙
- 【模型结构绘制】深度学习神经网络模型结构图绘制工具及方法总结【写论文必备】
- Linux积累 - scp 远程复制 加端口
- 指针数组和指向指针的指针
- c++基础知识点(6)类的继承,构造,析构顺序,虚继承等
- 90后小伙用果酱画画:花鸟鱼虫活灵活现(图)
- Linux(入门基础):04---文件的压缩、解压、打包(gzip、bzip2、xz、tar)
- FFmpeg浅尝辄止(四)——音频的解码和编码
- java 修改gps,改机 - 从源码着手任意修改GPS地理位置
- 输入输出系统:M/M/1排队系统例题
- PACE——深度神经网络测试的实用准确度估计方法
- 配置注册表数据库损坏
热门文章
- ehcache入门基础示例
- Android studio 如何导入并引用Library工程
- Hyper-V Server 存储分层
- 教程-TObjectList.Clear、TStringList.Clear方法对象有没有被释放
- LastPass 的开源替代品
- 空位補零,你會選擇哪種方式?
- javascript小技巧(转自DooIT)http://www.cnblogs.com/ttyp/archive/2004/11/15/63900.html
- 操作日志和系统日志分类记录
- 简述数学建模的过程_【数学建模的基本工作流程】作业帮
- mysql查看脚本错误位置_记一次mysql启动不了查找经历