企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
虽然Java层Binder系统是Native层Binder系统的一个Mirror,但这个Mirror终归还需借助Native层Binder系统来开展工作,即Mirror和Native层Binder有着千丝万缕的关系,一定要在Java层Binder正式工作之前建立这种关系。下面分析Java层Binder框架是如何初始化的。 在Android系统中,在Java初创时期,系统会提前注册一些JNI函数,其中有一个函数专门负责搭建Java Binder和Native Binder交互关系,该函数是register\_android\_os\_Binder,代码如下: **android_util_Binder.cpp-->register_android_os_Binder()** ``` int register_android_os_Binder(JNIEnv* env) { // 初始化Java Binder类和Native层的关系 if(int_register_android_os_Binder(env) < 0) return -1; // 初始化Java BinderInternal类和Native层的关系 if(int_register_android_os_BinderInternal(env) < 0) return -1; // 初始化Java BinderProxy类和Native层的关系 if(int_register_android_os_BinderProxy(env) < 0) return -1; ...... return0; } ``` 据上面的代码可知,register\_android\_os\_Binder函数完成了Java Binder架构中最重要的3个类的初始化工作。 #### 1. Binder类的初始化 int\_register\_android\_os\_Binder函数完成了Binder类的初始化工作,代码如下: **android_util_Binder.cpp-->int_register_android_os_Binder()** ``` static int int_register_android_os_Binder(JNIEnv*env) { jclassclazz; //kBinderPathName为Java层中Binder类的全路径名,“android/os/Binder“ clazz =env->FindClass(kBinderPathName); /*gBinderOffSets是一个静态类对象,它专门保存Binder类的一些在JNI层中使用的信息, 如成员函数execTranscat的methodID,Binder类中成员mObject的fildID */ gBinderOffsets.mClass = (jclass) env->NewGlobalRef(clazz); gBinderOffsets.mExecTransact =env->GetMethodID(clazz, "execTransact", "(IIII)Z"); gBinderOffsets.mObject =env->GetFieldID(clazz, "mObject", "I"); // 注册Binder类中native函数的实现 returnAndroidRuntime::registerNativeMethods( env,kBinderPathName, gBinderMethods,NELEM(gBinderMethods)); } ``` 从上面代码可知,gBinderOffsets对象保存了和Binder类相关的某些在JNI层中使用的信息。它们将用来在JNI层对Java层的Binder对象进行操作。execTransact()函数以及mObject成员的用途将在2.2.3节介绍。 * * * * * **建议** 如果读者对JNI不是很清楚,可参阅卷I第2章“深入理解JNI”。 * * * * * #### 2. BinderInternal类的初始化 下一个初始化的类是BinderInternal,其代码在int\_register\_android\_os\_BinderInternal函数中。 **android_util_Binder.cpp-->int_register_android_os_BinderInternal()** ``` static intint_register_android_os_BinderInternal(JNIEnv* env) { jclassclazz; // 根据BinderInternal的全路径名找到代表该类的jclass对象。全路径名为 //“com/android/internal/os/BinderInternal” clazz =env->FindClass(kBinderInternalPathName); //gBinderInternalOffsets也是一个静态对象,用来保存BinderInternal类的一些信息 gBinderInternalOffsets.mClass = (jclass) env->NewGlobalRef(clazz); // 获取forceBinderGc的methodID gBinderInternalOffsets.mForceGc = env->GetStaticMethodID(clazz, "forceBinderGc","()V"); // 注册BinderInternal类中native函数的实现 returnAndroidRuntime::registerNativeMethods( env,kBinderInternalPathName, gBinderInternalMethods, NELEM(gBinderInternalMethods)); } ``` int\_register\_android\_os\_BinderInternal的工作内容和int\_register\_android\_os\_Binder的工作内容类似: - 获取一些有用的methodID和fieldID。这表明JNI层一定会向上调用Java层的函数。 - 注册相关类中native函数的实现。 #### 3. BinderProxy类的初始化 int\_register\_android\_os\_BinderProxy完成了BinderProxy类的初始化工作,代码稍显复杂,如下所示: **android_util_Binder.cpp-->int_register_android_os_BinderProxy()** ``` static intint_register_android_os_BinderProxy(JNIEnv* env) { jclassclazz; // **① gWeakReferenceOffsets用来和WeakReference类打交道** clazz =env->FindClass("java/lang/ref/WeakReference"); gWeakReferenceOffsets.mClass = (jclass) env->NewGlobalRef(clazz); // 获取WeakReference类get函数的MethodID gWeakReferenceOffsets.mGet= env->GetMethodID(clazz, "get", "()Ljava/lang/Object;"); // **② gErrorOffsets用来和Error类打交道** clazz =env->FindClass("java/lang/Error"); gErrorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); // **③ gBinderProxyOffsets用来和BinderProxy类打交道** clazz =env->FindClass(kBinderProxyPathName); gBinderProxyOffsets.mClass = (jclass) env->NewGlobalRef(clazz); gBinderProxyOffsets.mConstructor= env->GetMethodID(clazz,"<init>", "()V"); ......//获取BinderProxy的一些信息 // **④ gClassOffsets用来和Class类打交道** clazz =env->FindClass("java/lang/Class"); gClassOffsets.mGetName =env->GetMethodID(clazz, "getName","()Ljava/lang/String;"); // 注册BinderProxy native函数的实现 returnAndroidRuntime::registerNativeMethods(env, kBinderProxyPathName,gBinderProxyMethods, NELEM(gBinderProxyMethods)); } ``` 据上面代码可知,int\_register\_android\_os\_BinderProxy函数除了初始化BinderProxy类外,还获取了WeakReference类和Error类的一些信息。看来BinderProxy对象的生命周期会委托WeakReference来管理,难怪JNI层会获取该类get函数的MethodID。 至此,Java Binder几个重要成员的初始化已完成,同时在代码中定义了几个全局静态对象,分别是gBinderOffsets、gBinderInternalOffsets和gBinderProxyOffsets。 框架的初始化其实就是提前获取一些JNI层的使用信息,如类成员函数的MethodID,类成员变量的fieldID等。这项工作是必需的,因为它能节省每次使用时获取这些信息的时间。当Binder调用频繁时,这些时间累积起来还是不容小觑的。 另外,这个过程中所创建的几个全局静态对象为JNI层访问Java层的对象提供了依据。而在每个初始化函数中所执行的registerNativeMethods()方法则为Java层访问JNI层打通了道路。换句话说,Binder初始化的工作就是通过JNI建立起Native Binder与Java Binder之间互相通信的桥梁。 下面通过一个例子来分析Java Binder的工作流程。