引言:分析Android源码6.0的过程,一定离不开Java与C/C++代码直接的来回跳转,那么就很有必要掌握JNI,这是链接Java层和Native层的桥梁,本文涉及相关源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
frameworks/base/core/jni/AndroidRuntime.cpp libcore/luni/src/main/java/java/lang/System.java libcore/luni/src/main/java/java/lang/Runtime.java libnativehelper/JNIHelp.cpp libnativehelper/include/nativehelper/jni.h frameworks/base/core/java/android/os/MessageQueue.java frameworks/base/core/jni/android_os_MessageQueue.cpp frameworks/base/core/java/android/os/Binder.java frameworks/base/core/jni/android_util_Binder.cpp frameworks/base/media/java/android/media/MediaPlayer.java frameworks/base/media/jni/android_media_MediaPlayer.cppc |
一、JNI概述
JNI(Java Native Interface,Java本地接口),用于打通Java层与Native(C/C++)层。这不是Android系统所独有的,而是Java所有。众所周知,Java语言是跨平台的语言,而这跨平台的背后都是依靠Java虚拟机,虚拟机采用C/C++编写,适配各个系统,通过JNI为上层Java提供各种服务,保证跨平台性。
相信不少经常使用Java的程序员,享受着其跨平台性,可能全然不知JNI的存在。在Android平台,让JNI大放异彩,为更多的程序员所熟知,往往为了提供效率或者其他功能需求,就需要NDK开发。上一篇文章 Linux系统调用(syscall)原理,介绍了打通android上层与底层kernel的枢纽syscall,那么本文的目的则是介绍打通android上层中Java层与Native的纽带JNI。
二、JNI查找方式
Android系统在启动启动过程中,先启动Kernel创建init进程,紧接着由init进程fork第一个横穿Java和C/C++的进程,即Zygote进程。Zygote启动过程中会AndroidRuntime.cpp
中的startVm
创建虚拟机,VM创建完成后,紧接着调用startReg
完成虚拟机中的JNI方法注册。
2.1 startReg
[–>AndroidRuntime.cpp]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
int AndroidRuntime::startReg(JNIEnv* env) { //设置线程创建方法为javaCreateThreadEtc androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc); env->PushLocalFrame(200); //进程NI方法的注册 if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) { env->PopLocalFrame(NULL); return -1; } env->PopLocalFrame(NULL); return 0; } |
register_jni_procs(gRegJNI, NELEM(gRegJNI), env)这行代码的作用就是就是循环调用gRegJNI
数组成员所对应的方法。
1 2 3 4 5 6 7 8 9 |
static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env) { for (size_t i = 0; i < count; i++) { if (array[i].mProc(env) < 0) { return -1; } } return 0; } |
gRegJNI
数组,有100多个成员变量,定义在AndroidRuntime.cpp
:
1 2 3 4 5 |
static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_os_MessageQueue), REG_JNI(register_android_os_Binder), ... }; |
该数组的每个成员都代表一个类文件的jni映射,其中REG_JNI是一个宏定义,在Zygote中介绍过,该宏的作用就是调用相应的方法。
2.2 如何查找native方法
当大家在看framework层代码时,经常会看到native方法,这是往往需要查看所对应的C++方法在哪个文件,对应哪个方法?下面从一个实例出发带大家如何查看java层方法所对应的native方法位置。
2.2.1 实例(一)
当分析Android消息机制源码,遇到MessageQueue.java
中有多个native方法,比如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
frameworks/base/core/jni/AndroidRuntime.cpp libcore/luni/src/main/java/java/lang/System.java libcore/luni/src/main/java/java/lang/Runtime.java libnativehelper/JNIHelp.cpp libnativehelper/include/nativehelper/jni.h frameworks/base/core/java/android/os/MessageQueue.java frameworks/base/core/jni/android_os_MessageQueue.cpp frameworks/base/core/java/android/os/Binder.java frameworks/base/core/jni/android_util_Binder.cpp frameworks/base/media/java/android/media/MediaPlayer.java frameworks/base/media/jni/android_media_MediaPlayer.cppc |
一、JNI概述
JNI(Java Native Interface,Java本地接口),用于打通Java层与Native(C/C++)层。这不是Android系统所独有的,而是Java所有。众所周知,Java语言是跨平台的语言,而这跨平台的背后都是依靠Java虚拟机,虚拟机采用C/C++编写,适配各个系统,通过JNI为上层Java提供各种服务,保证跨平台性。
相信不少经常使用Java的程序员,享受着其跨平台性,可能全然不知JNI的存在。在Android平台,让JNI大放异彩,为更多的程序员所熟知,往往为了提供效率或者其他功能需求,就需要NDK开发。上一篇文章 Linux系统调用(syscall)原理,介绍了打通android上层与底层kernel的枢纽syscall,那么本文的目的则是介绍打通android上层中Java层与Native的纽带JNI。
二、JNI查找方式
Android系统在启动启动过程中,先启动Kernel创建init进程,紧接着由init进程fork第一个横穿Java和C/C++的进程,即Zygote进程。Zygote启动过程中会AndroidRuntime.cpp
中的startVm
创建虚拟机,VM创建完成后,紧接着调用startReg
完成虚拟机中的JNI方法注册。
2.1 startReg
[–>AndroidRuntime.cpp]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
int AndroidRuntime::startReg(JNIEnv* env) { //设置线程创建方法为javaCreateThreadEtc androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc); env->PushLocalFrame(200); //进程NI方法的注册 if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) { env->PopLocalFrame(NULL); return -1; } env->PopLocalFrame(NULL); return 0; } |
register_jni_procs(gRegJNI, NELEM(gRegJNI), env)这行代码的作用就是就是循环调用gRegJNI
数组成员所对应的方法。
1 2 3 4 5 6 7 8 9 |
static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env) { for (size_t i = 0; i < count; i++) { if (array[i].mProc(env) < 0) { return -1; } } return 0; } |
gRegJNI
数组,有100多个成员变量,定义在AndroidRuntime.cpp
:
1 2 3 4 5 |
static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_os_MessageQueue), REG_JNI(register_android_os_Binder), ... }; |
该数组的每个成员都代表一个类文件的jni映射,其中REG_JNI是一个宏定义,在Zygote中介绍过,该宏的作用就是调用相应的方法。
2.2 如何查找native方法
当大家在看framework层代码时,经常会看到native方法,这是往往需要查看所对应的C++方法在哪个文件,对应哪个方法?下面从一个实例出发带大家如何查看java层方法所对应的native方法位置。
2.2.1 实例(一)
当分析Android消息机制源码,遇到MessageQueue.java
中有多个native方法,比如: