本文内容很多触及 JNI 编程基础,假如不太熟悉能够提前阅读JNI 编程上手攻略
1. Framework 层的 JNI 函数封装
Framework 对常用的 JNI 函数做了封装:
namespace android {
//查找对应Java类
static inline jclass FindClassOrDie(JNIEnv* env, const char* class_name) {
jclass clazz = env->FindClass(class_name);
LOG_ALWAYS_FATAL_IF(clazz == NULL, "Unable to find class %s", class_name);
return clazz;
}
//回来类的实例域 ID
static inline jfieldID GetFieldIDOrDie(JNIEnv* env, jclass clazz, const char* field_name,
const char* field_signature) {
jfieldID res = env->GetFieldID(clazz, field_name, field_signature);
LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find static field %s", field_name);
return res;
}
//回来 Java 类或者接口实例非静态办法的办法 ID
static inline jmethodID GetMethodIDOrDie(JNIEnv* env, jclass clazz, const char* method_name,
const char* method_signature) {
jmethodID res = env->GetMethodID(clazz, method_name, method_signature);
LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find method %s", method_name);
return res;
}
//回来类的静态域的属性 ID
static inline jfieldID GetStaticFieldIDOrDie(JNIEnv* env, jclass clazz, const char* field_name,
const char* field_signature) {
jfieldID res = env->GetStaticFieldID(clazz, field_name, field_signature);
LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find static field %s", field_name);
return res;
}
//回来类的静态办法 ID
static inline jmethodID GetStaticMethodIDOrDie(JNIEnv* env, jclass clazz, const char* method_name,
const char* method_signature) {
jmethodID res = env->GetStaticMethodID(clazz, method_name, method_signature);
LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find static method %s", method_name);
return res;
}
//根据局部引证创立一个全局引证
template <typename T>
static inline T MakeGlobalRefOrDie(JNIEnv* env, T in) {
jobject res = env->NewGlobalRef(in);
LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to create global reference.");
return static_cast<T>(res);
}
//注册 Java 类对应的 JNI 办法
static inline int RegisterMethodsOrDie(JNIEnv* env, const char* className,
const JNINativeMethod* gMethods, int numMethods) {
int res = AndroidRuntime::registerNativeMethods(env, className, gMethods, numMethods);
LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
return res;
}
/**
* Read the specified field from jobject, and convert to std::string.
* If the field cannot be obtained, return defaultValue.
*/
static inline std::string getStringField(JNIEnv* env, jobject obj, jfieldID fieldId,
const char* defaultValue) {
ScopedLocalRef<jstring> strObj(env, jstring(env->GetObjectField(obj, fieldId)));
if (strObj != nullptr) {
ScopedUtfChars chars(env, strObj.get());
return std::string(chars.c_str());
}
return std::string(defaultValue);
}
} // namespace android
#endif // CORE_JNI_HELPERS
上述封装中触及到了 LOG_ALWAYS_FATAL_IF 宏,该宏用于记录一个丧命错误。假如给定的条件失败,这将中止程序。像一般断言一样履行,但会生成给定的音讯。该功用不会从 release 版别中剥离。需求留意的是,条件测试与正常的 assert() 语义相反。
FindClass,GetFieldID,NewGlobalRef
等 JNI 函数在调用进程中都可能发生反常,咱们在JNI 编程上手攻略之反常处理中介绍了处理这类反常的一般手法,framework 中的处理稍有不同,当出现反常时,直接通过 LOG_ALWAYS_FATAL_IF 宏中止程序。
2. Java 层初始化
Android Zygote 启动时,会调用 AndroidRuntime::startReg
注册一系列的 JNI 办法,其中包含了 Java 层与 Binder 相关的 JNI 办法:
// frameworks/base/core/jni/AndroidRuntime.cpp
static const RegJNIRec gRegJNI[] = {
//...
REG_JNI(register_android_os_Binder),
//...
}
int AndroidRuntime::startReg(JNIEnv* env)
{
//......
//注册 jni 函数
if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
env->PopLocalFrame(NULL);
return -1;
}
//......
return 0;
}
上面的代码注册了一系列的 JNI 办法,其中 gRegJNI 是一个数组,保存了一系列的待注册的 JNI 办法列表, 其中的 register_android_os_Binder 就是与 Binder 的 JNI 函数注册相关的。
register_android_os_Binder 是一个函数指针,咱们来看一下它的具体完成:
// frameworks/base/core/jni/android_util_Binder.cpp
int register_android_os_Binder(JNIEnv* env)
{
//注册 Binder 类的 JNI 办法
if (int_register_android_os_Binder(env) < 0)
return -1;
//注册 BinderInteral 类的 JNI 办法
if (int_register_android_os_BinderInternal(env) < 0)
return -1;
//注册 BinderProxy 类的 JNI 办法
if (int_register_android_os_BinderProxy(env) < 0)
return -1;
//......
return 0;
}
这儿依次调用了三个办法来注册 JNI 办法,咱们以第一个为例来剖析:
static int int_register_android_os_Binder(JNIEnv* env)
{
jclass clazz = FindClassOrDie(env, kBinderPathName);
gBinderOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z");
gBinderOffsets.mGetInterfaceDescriptor = GetMethodIDOrDie(env, clazz, "getInterfaceDescriptor",
"()Ljava/lang/String;");
gBinderOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");
return RegisterMethodsOrDie(
env, kBinderPathName,
gBinderMethods, NELEM(gBinderMethods));
}
//函数触及到的其他变量
static const JNINativeMethod gBinderMethods[] = {
{ "getCallingPid", "()I", (void*)android_os_Binder_getCallingPid },
{ "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid },
{ "isHandlingTransaction", "()Z", (void*)android_os_Binder_isHandlingTransaction },
{ "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 },
{ "setCallingWorkSourceUid", "(I)J", (void*)android_os_Binder_setCallingWorkSourceUid },
{ "getCallingWorkSourceUid", "()I", (void*)android_os_Binder_getCallingWorkSourceUid },
{ "clearCallingWorkSource", "()J", (void*)android_os_Binder_clearCallingWorkSource },
{ "restoreCallingWorkSource", "(J)V", (void*)android_os_Binder_restoreCallingWorkSource },
{ "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 }
};
static struct bindernative_offsets_t
{
// Class state.
jclass mClass;
jmethodID mExecTransact;
jmethodID mGetInterfaceDescriptor;
// Object state.
jfieldID mObject;
} gBinderOffsets;
const char* const kBinderPathName = "android/os/Binder";
int_register_android_os_Binder
的操作很简单,就是把 android/os/Binder
的部分成员 ID 保存到全局结构体变量 gBinderOffsets 中,这么做的原因咱们在JNI 编程上手攻略之 JNI 调用功能优化 中说过,首要是为了进步 JNI 调用的功能。最终再调用 RegisterMethodsOrDie
将 gBinderMethods
数组中的函数注册到 JVM,这样 android/os/Binder
中界说的 Native 办法才能正常调用。
别的两个函数 int_register_android_os_BinderInternal
和 int_register_android_os_BinderProxy
的履行流程基本是一模一样。留给读者自行剖析。
总结
通过上面的剖析咱们应该知道, Java 层中的三个类 BinderProxy BinderInternal Binder 是在 zygote 中启动一个新进程,初始化 JVM 环境时注册的 Native 办法,当履行到这三个类的 Native 办法时,咱们应该到 frameworks/base/core/jni/android_util_Binder.cpp
文件中去查看其 Native 完成。
关于
我叫阿豪,2015 年本科结业于国防科技大学指挥自动化专业,结业后,在某单位从事信息化装备的研制工作。首要研究方向为 Android Framework 与 Linux Kernel,2023年春节后开始做 Android Framework 相关的技术共享。
假如你对 Framework 感兴趣或者正在学习 Framework,能够参考我总结的Android Framework 学习路线攻略,也可重视我的微信大众号,我会在大众号上继续共享我的经历,帮助正在学习的你少走一些弯路。学习进程中假如你有疑问或者你的经历想要共享给大家能够增加我的微信,我拉你进技术交流群。