本章關鍵點總結 & 說明:java
這裏關注➕Binder Java層實現中 JNI層開機初始化部分,主要談關鍵類Binder、BinderInternal、BinderProxy的開機初始化流程。android
初始化Java層Binder框架(JNI的註冊)架構
Java層Binder系統是在C++ 層Binder上經過JNI創建的,同時在開機時必定要在Java層Binder正式工做以前創建這種關係。這裏主要分析Java層Binder框架是如何初始化。框架
在Android系統中,在Java初創時期,系統會提早註冊一些JNI函數,其中有一個函數專門負責搭建Java Binder和Native Binder交互關係,該函數是register_android_os_Binder,代碼以下:函數
int register_android_os_Binder(JNIEnv* env)
{
if (int_register_android_os_Binder(env) < 0) //初始化Java Binder類和Native層的關係
return -1;
if (int_register_android_os_BinderInternal(env) < 0)//初始化Java BinderInternal類和Native層的關係
return -1;
if (int_register_android_os_BinderProxy(env) < 0) //初始化Java BinderProxy類和Native層的關係
return -1;
jclass clazz;
clazz = env->FindClass("android/util/Log");
LOG_FATAL_IF(clazz == NULL, "Unable to find class android.util.Log");
gLogOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
gLogOffsets.mLogE = env->GetStaticMethodID(
clazz, "e", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I");
assert(gLogOffsets.mLogE);
clazz = env->FindClass("android/os/ParcelFileDescriptor");
LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor");
gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
gParcelFileDescriptorOffsets.mConstructor
= env->GetMethodID(clazz, "<init>", "(Ljava/io/FileDescriptor;)V");
clazz = env->FindClass("android/os/StrictMode");
LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.StrictMode");
gStrictModeCallbackOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
gStrictModeCallbackOffsets.mCallback = env->GetStaticMethodID(
clazz, "onBinderStrictModePolicyChange", "(I)V");
LOG_FATAL_IF(gStrictModeCallbackOffsets.mCallback == NULL,
"Unable to find strict mode callback.");
return 0;
}
據上面的代碼可知,register_android_os_Binder函數完成了Java Binder架構中最重要的3個類的初始化工做。接下來繼續分析註冊Binder、BinderInternal、BinderProxy的過程對象
1 int_register_android_os_Binderblog
int_register_android_os_Binder函數完成了Binder類的初始化工做,代碼以下:ip
static int int_register_android_os_Binder(JNIEnv* env)
{
jclass clazz;
//kBinderPathName爲Java層中Binder類的全路徑名,「android/os/Binder「
clazz = env->FindClass(kBinderPathName);
LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Binder");
//gBinderOffSets是一個靜態類對象,它專門保存Binder類的一些在JNI層中使用的信息,
//如成員函數execTranscat的methodID,Binder類中成員mObject的fildID
gBinderOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
gBinderOffsets.mExecTransact = env->GetMethodID(clazz, "execTransact", "(IJJI)Z");
assert(gBinderOffsets.mExecTransact);
gBinderOffsets.mObject = env->GetFieldID(clazz, "mObject", "J");
assert(gBinderOffsets.mObject);
//註冊Binder類中native函數的實現
return AndroidRuntime::registerNativeMethods(env, kBinderPathName,gBinderMethods, NELEM(gBinderMethods));
}
從上面代碼可知,gBinderOffsets對象保存了和Binder類相關的某些在JNI層中使用的信息。ci
2 int_register_android_os_BinderInternalget
int_register_android_os_BinderInternal函數完成了BinderInternal類的初始化,代碼以下:
static int int_register_android_os_BinderInternal(JNIEnv* env)
{
jclass clazz;
//kBinderInternalPathName爲Java層中BinderInternal類的全路徑名,「com/android/internal/os/BinderInternal」
clazz = env->FindClass(kBinderInternalPathName);
LOG_FATAL_IF(clazz == NULL, "Unable to find class com.android.internal.os.BinderInternal");
//gBinderInternalOffsets也是一個靜態對象,用來保存BinderInternal類的一些信息
gBinderInternalOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
//獲取forceBinderGc的methodID
gBinderInternalOffsets.mForceGc = env->GetStaticMethodID(clazz, "forceBinderGc", "()V");
assert(gBinderInternalOffsets.mForceGc);
//註冊BinderInternal類中native函數的實現
return AndroidRuntime::registerNativeMethods(env, kBinderInternalPathName,
gBinderInternalMethods, NELEM(gBinderInternalMethods));
}
同上,獲取一些有用的methodID和fieldID。這代表JNI層必定會向上調用Java層的函數。註冊相關類中native函數的實現。
3 int_register_android_os_BinderProxy
int_register_android_os_BinderProxy完成了BinderProxy類的初始化工做,代碼稍顯複雜,以下所示:
static int int_register_android_os_BinderProxy(JNIEnv* env) { jclass clazz; //gErrorOffsets用來和Error類打交道 clazz = env->FindClass("java/lang/Error"); LOG_FATAL_IF(clazz == NULL, "Unable to find class java.lang.Error"); gErrorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); //gBinderProxyOffsets用來和BinderProxy類打交道 clazz = env->FindClass(kBinderProxyPathName); LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.BinderProxy"); //獲取BinderProxy的一些信息 gBinderProxyOffsets.mClass = (jclass) env->NewGlobalRef(clazz); gBinderProxyOffsets.mConstructor = env->GetMethodID(clazz, "<init>", "()V"); assert(gBinderProxyOffsets.mConstructor); gBinderProxyOffsets.mSendDeathNotice = env->GetStaticMethodID(clazz, "sendDeathNotice", "(Landroid/os/IBinder$DeathRecipient;)V"); assert(gBinderProxyOffsets.mSendDeathNotice); gBinderProxyOffsets.mObject = env->GetFieldID(clazz, "mObject", "J"); assert(gBinderProxyOffsets.mObject); gBinderProxyOffsets.mSelf = env->GetFieldID(clazz, "mSelf", "Ljava/lang/ref/WeakReference;"); assert(gBinderProxyOffsets.mSelf); gBinderProxyOffsets.mOrgue = env->GetFieldID(clazz, "mOrgue", "J"); assert(gBinderProxyOffsets.mOrgue); //gClassOffsets用來和Class類打交道 clazz = env->FindClass("java/lang/Class"); LOG_FATAL_IF(clazz == NULL, "Unable to find java.lang.Class"); gClassOffsets.mGetName = env->GetMethodID(clazz, "getName", "()Ljava/lang/String;"); assert(gClassOffsets.mGetName); //註冊BinderProxy native函數的實現 return AndroidRuntime::registerNativeMethods(env, kBinderProxyPathName, gBinderProxyMethods, NELEM(gBinderProxyMethods)); } 至此,Java Binder幾個重要成員的初始化已完成,同時在代碼中定義了幾個全局靜態對象,分別是gBinderOffsets、gBinderInternalOffsets和gBinderProxyOffsets。框架的初始化其實就是提早獲取一些JNI層的使用信息,如類成員函數的MethodID,類成員變量的fieldID等。這項工做是必需的,由於它能節省每次使用時獲取這些信息的時間。當Binder調用頻繁時,這些時間累積起來仍是不容小覷的。