Android系统的JNI原理分析(二)- 数据类型转换和方法签名
声明
- 前阶段在项目中使用了Android的JNI技术,在此文中做些技术知识总结。
- 本文参考了一些书籍的若干章节,比如《Android进阶解密-第9章-JNI原理》、《深入理解Android虚拟机-第4章-分析JNI》、《深入理解Android系统-第2章-分析JNI》、《Android NDK Beginner_'s Guide》等
- 本文使用的代码时LineageOS的cm-14.1,对应Android 7.1.2,可以参考我的另一篇博客:cm-14.1 Android系统启动过程分析(〇)-如何下载Nexus5的LineageOS14.1(cm-14.1)系统源码并编译、刷机
1 Java层和JNI层的数据类型转换
进入到源码路径:
vim ~/LineageOS/frameworks/base/media/jni/android_
media_MediaRecorder.cpp,查看函数android_media_MediaRecorder_native_setup:
static void
android_media_MediaRecorder_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,jstring packageName, jstring opPackageName)
{ALOGV("setup");ScopedUtfChars opPackageNameStr(env, opPackageName);sp<MediaRecorder> mr = new MediaRecorder(String16(opPackageNameStr.c_str()));if (mr == NULL) {jniThrowException(env, "java/lang/RuntimeException", "Out of memory");return;}if (mr->initCheck() != NO_ERROR) {jniThrowException(env, "java/lang/RuntimeException", "Unable to initialize media recorder");return;}// create new listener and give it to MediaRecordersp<JNIMediaRecorderListener> listener = new JNIMediaRecorderListener(env, thiz, weak_this);mr->setListener(listener);// Convert client name jstring to String16const char16_t *rawClientName = reinterpret_cast<const char16_t*>(env->GetStringChars(packageName, NULL));jsize rawClientNameLen = env->GetStringLength(packageName);String16 clientName(rawClientName, rawClientNameLen);env->ReleaseStringChars(packageName,reinterpret_cast<const jchar*>(rawClientName));// pass client package name for permissions trackingmr->setClientName(clientName);setMediaRecorder(env, thiz, mr);
}
其中jobject、jstring类型参数都是JNI层的数据类型,Java层数据类型到JNI层就要转换为JNI层数据结构。包括基本数据类型和引用数据类型
1.1 Java层至JNI层基本数据类型的转换
Java类型 | JNI类型 | C++类型 | 关系描述 | 签名 | 占内存大小 |
---|---|---|---|---|---|
boolean | jboolean | unsigned char 或 unit8_t | 布尔类型 | Z | 1 |
int | jint | int或long | 整形 | I | 4 |
float | jfloat | float | 单精度类型 | F | 4 |
double | jdouble | double | 双精度类型 | D | 8 |
long | jlong | long | 长整形 | J | 8 |
short | jshort | short | 短整型 | S | 2 |
char | jchar | unsigned short | 字符 | C | 2 |
byte | jbyte | signed char | 字节类型 | B | 1 |
void | void | void | 空类型 | V |
从转换表中可以看出Java层基本数据类型转换到JNI层只需将数据类型前加个“j”即可(除了void类型)。
1.2 Java层至JNI层引用数据类型的转换
Java | Native | 签名(以;结尾) |
---|---|---|
所有对象 | jobject | L+classname +; |
Class | jclass | Ljava/lang/Clas; |
String | jstring | Ljava/lang/String; |
Trowable | jthrowable | Ljava/lang/Throwable; |
Object[] | jobjectArray | [L+classname +; |
byte[] | jbyteArray | [B |
char[] | jcharArray | [C |
double[] | jdoubleArray | [D |
float[] | jfloatArray | [F |
int[] | jintArray | [I |
short[] | jshortArray | [S |
long[] | jlongArray | [J |
boolean[] | jbooleanArray | [Z |
以~/LineageOS/frameworks/base/media/java/android/media/
MediaRecorder.java中的native_setup方法为例:
private native final void native_setup(Object mediarecorder_this,String clientName, String opPackageName) throws IllegalStateException;
对应在~/LineageOS/frameworks/base/media/jni/android_
media_MediaRecorder.cpp,查看函数android_media_MediaRecorder_native_setup:
static void
android_media_MediaRecorder_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,jstring packageName, jstring opPackageName)
{...省略n行...
}
可以发现:Object类型转换为jobject类型,String类型转换为jstring类型。
2 方法签名
进入到源码路径: vim ~/LineageOS/frameworks/base/media/jni/
android_media_MediaRecorder.cpp,在数组gMethods[]中可看到签名信息:
static const JNINativeMethod gMethods[] = {{"setCamera", "(Landroid/hardware/Camera;)V", (void *)android_media_MediaRecorder_setCamera},{"setVideoSource", "(I)V", (void *)android_media_MediaRecorder_setVideoSource},{"setAudioSource", "(I)V", (void *)android_media_MediaRecorder_setAudioSource},{"setOutputFormat", "(I)V", (void *)android_media_MediaRecorder_setOutputFormat},{"setVideoEncoder", "(I)V", (void *)android_media_MediaRecorder_setVideoEncoder},{"setAudioEncoder", "(I)V", (void *)android_media_MediaRecorder_setAudioEncoder},{"setParameter", "(Ljava/lang/String;)V", (void *)android_media_MediaRecorder_setParameter},{"_setOutputFile", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaRecorder_setOutputFileFD},{"setVideoSize", "(II)V", (void *)android_media_MediaRecorder_setVideoSize},{"setVideoFrameRate", "(I)V", (void *)android_media_MediaRecorder_setVideoFrameRate},{"setMaxDuration", "(I)V", (void *)android_media_MediaRecorder_setMaxDuration},{"setMaxFileSize", "(J)V", (void *)android_media_MediaRecorder_setMaxFileSize},{"_prepare", "()V", (void *)android_media_MediaRecorder_prepare},{"getSurface", "()Landroid/view/Surface;", (void *)android_media_MediaRecorder_getSurface},{"getMaxAmplitude", "()I", (void *)android_media_MediaRecorder_native_getMaxAmplitude},{"start", "()V", (void *)android_media_MediaRecorder_start},{"stop", "()V", (void *)android_media_MediaRecorder_stop},{"pause", "()V", (void *)android_media_MediaRecorder_pause},{"resume", "()V", (void *)android_media_MediaRecorder_resume},{"native_reset", "()V", (void *)android_media_MediaRecorder_native_reset},{"release", "()V", (void *)android_media_MediaRecorder_release},{"native_init", "()V", (void *)android_media_MediaRecorder_native_init},{"native_setup", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)V",(void *)android_media_MediaRecorder_native_setup},{"native_finalize", "()V", (void *)android_media_MediaRecorder_native_finalize},{"native_setInputSurface", "(Landroid/view/Surface;)V", (void *)android_media_MediaRecorder_setInputSurface },
};
简单地说,存在签名的原因就是Java语言的方法是可以重载的,重载的方法名字相同而参数不同,所以JNI仅通过方法名无法确定对应的是重载的哪个方法,必须要参数签名来辅助其关联。
避免博客拖太长,后续参见下篇Android系统的JNI原理分析(三)- JNIEnv
Android系统的JNI原理分析(二)- 数据类型转换和方法签名相关推荐
- Android 6.0 JNI原理分析 和 Linux系统调用(syscall)原理
JNI原理 引言:分析Android源码6.0的过程,一定离不开Java与C/C++代码直接的来回跳转,那么就很有必要掌握JNI,这是链接Java层和Native层的桥梁,本文涉及相关源码: fram ...
- 理解Android系统的进程间通信原理(二)----RPC机制
理解Android系统中的轻量级解决方案RPC的原理,需要先回顾一下JAVA中的RMI(Remote Method Invocation)这个易于使用的纯JAVA方案(用来实现分布式应用).有关RMI ...
- Android系统root破解原理分析
上一篇文章 Android adb 源码分析 理论基础 root破解过程的终极目标是替换掉系统中的su程序.但是要想替换掉系统中su程序本身就是需要root权限的,怎样在root破解过程中获得root ...
- Android JNI原理分析
引言:分析Android源码6.0的过程,一定离不开Java与C/C++代码直接的来回跳转,那么就很有必要掌握JNI,这是链接Java层和Native层的桥梁,本文涉及相关源码: frameworks ...
- android 版本更新原理,Android系统Recovery工作原理之使用update.zip升级过程分析(二)...
Android系统Recovery工作原理之使用update.zip升级过程分析(二)---update.zip差分包问题的解决 在上一篇末尾提到的生成差分包时出现的问题,现已解决,由于最近比较忙,相 ...
- Android系统Recovery工作原理之使用update.zip升级过程分析(二)---u...
2019独角兽企业重金招聘Python工程师标准>>> Android系统Recovery工作原理之使用update.zip升级过程分析(二)---update.zip差分包问题的 ...
- Android系统Recovery工作原理之使用update.zip升级过程分析(五)
Android系统Recovery工作原理之使用update.zip升级过程分析(五)---update.zip包从上层进入Recovery服务文章开头我们就提到update.zip包来源有两种,一个 ...
- 基于Android系统的IPv6网络接入分析
基于Android系统的IPv6网络接入分析 摘 要:本文深入分析了 ...
- Android手机一键Root原理分析(作者:非虫,文章来自:《黑客防线》2012年7月)
之前几天都在做Android漏洞分析的项目,万幸发现了这篇文章.废话不多说,上文章! <Android手机一键Root原理分析> (作者:非虫,文章来自:<黑客防线>2012年 ...
最新文章
- python中文意思k-python中“//”表示什么意思_后端开发
- 8.初探python之集合
- 物联网对石油燃气行业的作用
- Netty入门篇-从双向通信开始
- mysql xp系统时间_mysql时间类型year
- 网络游戏中的数据包设计和定义(初论)
- 计算机二级科目有ps吗,计算机二级有ps吗
- 你们要的Windows IDEA 快捷键终极大全,速度收藏!
- 控制输入,非法字符不能输入到TextBox.
- 无线网络 设置网关和服务器,我家的网络连接的IP是 192.168.1.223 我想问网关是多少 服务器是...
- 腾达ap设置说明_腾达无线路由器ap模式如何设置
- c语言银行卡管理系统的意义,使用会员管理系统的意义
- Redis集群搭建(单设备,多设备)
- 未能加载“xxx”程序集
- xp计算机用户名在哪里设置路由器,XP如何设置无线路由器 XP无线路由器怎么设置?-192路由网...
- 2015-华为招聘公开测试题目-单词迷宫
- Android 11.0 修改添加的默认文件夹为9宫格样式
- 国内外可信计算技术发展概况(转载1)
- c++ 的vector、array和数组的比较
- (图解)设置封面中的下划线一样长