声明

  • 前阶段在项目中使用了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原理分析(二)- 数据类型转换和方法签名相关推荐

  1. Android 6.0 JNI原理分析 和 Linux系统调用(syscall)原理

    JNI原理 引言:分析Android源码6.0的过程,一定离不开Java与C/C++代码直接的来回跳转,那么就很有必要掌握JNI,这是链接Java层和Native层的桥梁,本文涉及相关源码: fram ...

  2. 理解Android系统的进程间通信原理(二)----RPC机制

    理解Android系统中的轻量级解决方案RPC的原理,需要先回顾一下JAVA中的RMI(Remote Method Invocation)这个易于使用的纯JAVA方案(用来实现分布式应用).有关RMI ...

  3. Android系统root破解原理分析

    上一篇文章 Android adb 源码分析 理论基础 root破解过程的终极目标是替换掉系统中的su程序.但是要想替换掉系统中su程序本身就是需要root权限的,怎样在root破解过程中获得root ...

  4. Android JNI原理分析

    引言:分析Android源码6.0的过程,一定离不开Java与C/C++代码直接的来回跳转,那么就很有必要掌握JNI,这是链接Java层和Native层的桥梁,本文涉及相关源码: frameworks ...

  5. android 版本更新原理,Android系统Recovery工作原理之使用update.zip升级过程分析(二)...

    Android系统Recovery工作原理之使用update.zip升级过程分析(二)---update.zip差分包问题的解决 在上一篇末尾提到的生成差分包时出现的问题,现已解决,由于最近比较忙,相 ...

  6. Android系统Recovery工作原理之使用update.zip升级过程分析(二)---u...

    2019独角兽企业重金招聘Python工程师标准>>>  Android系统Recovery工作原理之使用update.zip升级过程分析(二)---update.zip差分包问题的 ...

  7. Android系统Recovery工作原理之使用update.zip升级过程分析(五)

    Android系统Recovery工作原理之使用update.zip升级过程分析(五)---update.zip包从上层进入Recovery服务文章开头我们就提到update.zip包来源有两种,一个 ...

  8. 基于Android系统的IPv6网络接入分析

                                                                      基于Android系统的IPv6网络接入分析 摘 要:本文深入分析了 ...

  9. Android手机一键Root原理分析(作者:非虫,文章来自:《黑客防线》2012年7月)

    之前几天都在做Android漏洞分析的项目,万幸发现了这篇文章.废话不多说,上文章! <Android手机一键Root原理分析> (作者:非虫,文章来自:<黑客防线>2012年 ...

最新文章

  1. python中文意思k-python中“//”表示什么意思_后端开发
  2. 8.初探python之集合
  3. 物联网对石油燃气行业的作用
  4. Netty入门篇-从双向通信开始
  5. mysql xp系统时间_mysql时间类型year
  6. 网络游戏中的数据包设计和定义(初论)
  7. 计算机二级科目有ps吗,计算机二级有ps吗
  8. 你们要的Windows IDEA 快捷键终极大全,速度收藏!
  9. 控制输入,非法字符不能输入到TextBox.
  10. 无线网络 设置网关和服务器,我家的网络连接的IP是 192.168.1.223 我想问网关是多少 服务器是...
  11. 腾达ap设置说明_腾达无线路由器ap模式如何设置
  12. c语言银行卡管理系统的意义,使用会员管理系统的意义
  13. Redis集群搭建(单设备,多设备)
  14. 未能加载“xxx”程序集
  15. xp计算机用户名在哪里设置路由器,XP如何设置无线路由器 XP无线路由器怎么设置?-192路由网...
  16. 2015-华为招聘公开测试题目-单词迷宫
  17. Android 11.0 修改添加的默认文件夹为9宫格样式
  18. 国内外可信计算技术发展概况(转载1)
  19. c++ 的vector、array和数组的比较
  20. (图解)设置封面中的下划线一样长

热门文章

  1. Effective Java读书笔记
  2. 大学英语二_视听说单词
  3. wps,word缩印怎么设置
  4. opengl 点精灵的使用
  5. java计算机毕业设计 美食推荐系统 美食菜谱分享系统 食谱推荐系统 美食分享网站 java美食交流网站 营养食谱推荐系统
  6. cocos lua 接入google Play 排行榜
  7. 关于 chrome 谷歌浏览器 最小化后 页面被限制,不能运行的解决方案
  8. SpiFlash同步/异步读写单片机裸机实例
  9. 成都待慕电商:抖音商场频道上线公告
  10. 解决用友T6最新会计期间与最新会计日期不匹配的问题