本文首发于微信公众号「后厂技术官」html
关联系列
Android AOSP基础系列
Android系统启动系列
应用进程启动系列
Android深刻四大组件系列
Android深刻理解Context系列
Android深刻理解JNI系列
Android解析WindowManager
Android解析WMS系列
Android解析AMS系列
Android包管理机制系列
Android输入系统系列前端
原标题: Android Binder原理(六)Java Binder的初始化java
在Android Binder原理(一)学习Binder前必需要了解的知识点这篇文章中,我根据Android系统的分层,将Binder机制分为了三层:android
在此前的文章中,我一直都在介绍Native Binder和Kernel Binder的内容,它们的架构简单总结为下图。程序员
在Android Binder原理(二)ServiceManager中的Binder机制这篇文章中,我讲过BpBinder是Client端与Server交互的代理类,而BBinder则表明了Server端,那么上图就能够改成: 算法
Java Binder要想和Native Binder进行通讯,须要经过JNI,JNI的注册是在Zygote进程启动过程当中注册的,代码以下所示。
frameworks/base/core/jni/AndroidRuntime.cpp数组
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
...
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote) != 0) {//1
return;
}
onVmCreated(env);
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
...
}
复制代码
注释1处用于启动Java虚拟机,注释2处startReg函数用于完成虚拟机的JNI注册,关于AndroidRuntime的start函数的具体分析见Android系统启动流程(二)解析Zygote进程启动过程这篇文章。 startReg函数以下所示。 frameworks/base/core/jni/AndroidRuntime.cppbash
/*static*/ int AndroidRuntime::startReg(JNIEnv* env)
{
ATRACE_NAME("RegisterAndroidNatives");
androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
ALOGV("--- registering native functions ---\n");
env->PushLocalFrame(200);
if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {//1
env->PopLocalFrame(NULL);
return -1;
}
env->PopLocalFrame(NULL);
return 0;
}
复制代码
注释1处的register_jni_procs函数的做用就是循环调用gRegJNI数组的成员所对应的方法,以下所示。微信
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) {
#ifndef NDEBUG
ALOGD("----------!!! %s failed to load\n", array[i].mName);
#endif
return -1;
}
}
return 0;
}
复制代码
gRegJNI数组中有100多个成员变量:架构
static const RegJNIRec gRegJNI[] = {
REG_JNI(register_com_android_internal_os_RuntimeInit),
REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit),
REG_JNI(register_android_os_SystemClock),
...
REG_JNI(register_android_os_Binder),//1
...
};
复制代码
其中REG_JNI是一个宏定义:
#define REG_JNI(name) { name }
struct RegJNIRec {
int (*mProc)(JNIEnv*);
};
复制代码
实际上就是调用参数名所对应的函数。负责Java Binder和Native Binder通讯的函数为注释1处的register_android_os_Binder,代码以下所示。
frameworks/base/core/jni/android_util_Binder.cpp
int register_android_os_Binder(JNIEnv* env) {
//注册Binder类
if (int_register_android_os_Binder(env) < 0)
return -1;
//注册BinderInternal类
if (int_register_android_os_BinderInternal(env) < 0)
return -1;
//注册BinderProxy类
if (int_register_android_os_BinderProxy(env) < 0)
return -1;
...
return 0;
}
复制代码
register_android_os_Binder函数作了三件事,分别是: 1.注册Binder类 2.注册BinderInternal类 3.注册BinderProxy类
它们是Java Binder关联类的一小部分,它们的关系以下图所示。
FLAG_ONEWAY
的整形变量。客户端发起调用时,客户端通常会阻塞,直到服务端返回结果。设置FLAG_ONEWAY
后,客户端只须要把请求发送到服务端就能够当即返回,而不须要等待服务端的结果,这是一种非阻塞方式。下面分别对Binder、BinderInternal这两个类的注册进行分析。
调用int_register_android_os_Binder函数来完成Binder类的注册,代码以下所示。 frameworks/base/core/jni/android_util_Binder.cpp
static const JNINativeMethod gBinderMethods[] = {
/* name, signature, funcPtr */
{ "getCallingPid", "()I", (void*)android_os_Binder_getCallingPid },
{ "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid },
{ "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity },
{ "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity },
{ "setThreadStrictModePolicy", "(I)V", (void*)android_os_Binder_setThreadStrictModePolicy },
{ "getThreadStrictModePolicy", "()I", (void*)android_os_Binder_getThreadStrictModePolicy },
{ "flushPendingCommands", "()V", (void*)android_os_Binder_flushPendingCommands },
{ "getNativeBBinderHolder", "()J", (void*)android_os_Binder_getNativeBBinderHolder },
{ "getNativeFinalizer", "()J", (void*)android_os_Binder_getNativeFinalizer },
{ "blockUntilThreadAvailable", "()V", (void*)android_os_Binder_blockUntilThreadAvailable }
};
const char* const kBinderPathName = "android/os/Binder";//1
static int int_register_android_os_Binder(JNIEnv* env) {
jclass clazz = FindClassOrDie(env, kBinderPathName);//2
gBinderOffsets.mClass = MakeGlobalRefOrDie(env, clazz);//3
gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z");//4
gBinderOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");
return RegisterMethodsOrDie(
env, kBinderPathName,
gBinderMethods, NELEM(gBinderMethods));
}
复制代码
注释1处的kBinderPathName的值为"android/os/Binder",这是Binder在Java Binder中的全路径名。 注释2处根据这个路径名获取Binder的Class对象,并赋值给jclass类型的变量clazz,clazz是Java层Binder在JNI层的表明。 注释3处经过MakeGlobalRefOrDie函数将本地引用clazz转变为全局引用并赋值给gBinderOffsets.mClass。 注释4处用于找到Java层的Binder的成员方法execTransact并赋值给gBinderOffsets.mExecTransact。 注释5处用于找到Java层的Binder的成员变量mObject并赋值给gBinderOffsets.mObject。 最后一行经过RegisterMethodsOrDie函数注册gBinderMethods中定义的函数,其中gBinderMethods是JNINativeMethod类型的数组,里面存储的是Binder的Native方法(Java层)与JNI层函数的对应关系。
gBinderMethods的定义以下所示。
static struct bindernative_offsets_t {
jclass mClass;
jmethodID mExecTransact;
jfieldID mObject;
} gBinderOffsets;
复制代码
使用gBinderMethods来保存变量和方法有两个缘由: 1.为了效率考虑,若是每次调用相关的方法时都须要查询方法和变量,显然效率比较低。 2.这些成员变量和方法都是本地引用,在int int_register_android_os_Binder函数返回时,这些本地引用会被自动释放,所以用gBinderOffsets来保存,以便于后续使用。
对于JNI不大熟悉的同窗能够看Android深刻理解JNI(二)类型转换、方法签名和JNIEnv这篇文章。
调用int_register_android_os_BinderInternal函数来完成BinderInternal类的注册,代码以下所示。 frameworks/base/core/jni/android_util_Binder.cpp
const char* const kBinderInternalPathName = "com/android/internal/os/BinderInternal";
static int int_register_android_os_BinderInternal(JNIEnv* env) {
jclass clazz = FindClassOrDie(env, kBinderInternalPathName);
gBinderInternalOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
gBinderInternalOffsets.mForceGc = GetStaticMethodIDOrDie(env, clazz, "forceBinderGc", "()V");
gBinderInternalOffsets.mProxyLimitCallback = GetStaticMethodIDOrDie(env, clazz, "binderProxyLimitCallbackFromNative", "(I)V");
jclass SparseIntArrayClass = FindClassOrDie(env, "android/util/SparseIntArray");
gSparseIntArrayOffsets.classObject = MakeGlobalRefOrDie(env, SparseIntArrayClass);
gSparseIntArrayOffsets.constructor = GetMethodIDOrDie(env, gSparseIntArrayOffsets.classObject,
"<init>", "()V");
gSparseIntArrayOffsets.put = GetMethodIDOrDie(env, gSparseIntArrayOffsets.classObject, "put",
"(II)V");
BpBinder::setLimitCallback(android_os_BinderInternal_proxyLimitcallback);
return RegisterMethodsOrDie(
env, kBinderInternalPathName,
gBinderInternalMethods, NELEM(gBinderInternalMethods));
}
复制代码
和int_register_android_os_Binder函数的实现相似,主要作了三件事: 1.获取BinderInternal在JNI层的表明clazz。 2.将BinderInternal类中有用的成员变量和方法存储到gBinderInternalOffsets中。 3.注册BinderInternal类的Native方法对应的JNI函数。
还有一个BinderProxy类的注册,它和Binder、BinderInternal的注册过程差很少,这里就再也不赘述了,有兴趣的读者能够自行去看源码。
更多的内容请关注个人独立博客的知识体系:
liuwangshu.cn/system/
分享Java、Python、大数据、算法、大前端、AI相关技术,关注程序员技术提高和职场晋升,助力10W+程序员进阶为技术官和架构师!