android 系统核心机制binder(10)binder java层JNI初始化

112 篇文章 87 订阅

该系列文章总纲链接:专题分纲目录 android 系统核心机制 binder


本章关键点总结 & 说明:

这里关注➕Binder Java层实现中 JNI层开机初始化部分,主要谈关键类Binder、BinderInternal、BinderProxy的开机初始化流程。

初始化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_Binder

int_register_android_os_Binder函数完成了Binder类的初始化工作,代码如下:

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层中使用的信息。

2 int_register_android_os_BinderInternal

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调用频繁时,这些时间累积起来还是不容小觑的。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图王大胜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值