Skip to content

JNI层android_util_Binder

追踪 android_util_Binder.cpp 中 Java Binder、BinderProxy、JavaBBinderHolder 和 native IBinder 的双向转换。

基于android-17.0.0_r1
AndroidBinderJNIJava框架源码阅读

JNI层android_util_Binder ​

android_util_Binder.cpp 是 Java Binder 与 libbinder 的双向边界:Java Binder 通过 JavaBBinderHolder 变成 native JavaBBinderExt;native IBinder 通过 javaObjectForIBinder() 变成原 Java Binder 或 BinderProxy;死亡通知、冻结回调、线程池和 proxy 计数也在这里完成 JNI 注册和回调。

本文面向已经读过 Binder基类详解、BinderProxy详解、BinderInternal 和 Java-Parcel序列化 的读者。本文聚焦 JNI ownership、双向转换、回调列表和方法注册,不重复 Java API 或 native BpBinder 的全部实现。

1. 映射表 ​

1.1 Offset缓存 ​

源码文件:frameworks/base/core/jni/android_util_Binder.cpp

cpp
static struct bindernative_offsets_t {
    jclass mClass;
    jmethodID mExecTransact;
    jmethodID mGetInterfaceDescriptor;
    jmethodID mGetExtension;
    jfieldID mObject;
} gBinderOffsets;

static struct binderproxy_offsets_t {
    jclass mClass;
    jmethodID mGetInstance;
    jmethodID mSendDeathNotice;
    jmethodID mInvokeFrozenStateChangeCallback;
    jfieldID mNativeData;
} gBinderProxyOffsets;

JNI 注册阶段缓存 class、method 和 field ID,运行时用这些 ID 避免反复按名字查找。Binder 与 BinderProxy 的字段表分开维护:前者关注 mObject/execTransact,后者关注 mNativeData/回调。

1.2 方法注册 ​

cpp
static const JNINativeMethod gBinderMethods[] = {
    {"getCallingUid", "()I", ...},
    {"getNativeBBinderHolder", "()J", ...},
    {"getNativeFinalizer", "()J", ...},
    {"setExtensionNative", "(Landroid/os/IBinder;)V", ...},
};

int_register_android_os_Binder() 还取得 execTransact、descriptor 和 extension 方法 ID;注册失败会阻止 Java Binder native 方法可用。JNI 表是 ABI 边界,签名变更必须与 Java 声明同步。

2. Java到Native ​

2.1 Holder创建 ​

源码文件:frameworks/base/core/jni/android_util_Binder.cpp

cpp
static jlong android_os_Binder_getNativeBBinderHolder(...) {
    JavaBBinderHolder* jbh = new JavaBBinderHolder();
    return (jlong)jbh;
}

static void Binder_destroy(void* rawJbh) {
    JavaBBinderHolder* jbh =
            (JavaBBinderHolder*)rawJbh;
    delete jbh;
}

Java Binder 构造函数保存 holder 指针,并由 NativeAllocationRegistry 在 Java 对象不可达时调用 finalizer。holder 本身不等于已经创建的 JavaBBinderExt,它内部只保存一个弱引用。

2.2 Holder缓存 ​

cpp
sp<JavaBBinderExt> JavaBBinderHolder::get(
        JNIEnv* env, jobject obj) {
    sp<JavaBBinderExt> b;
    {
        AutoMutex lock(mLock);
        b = mBinder.promote();
    }
    if (b) return b;

    b = sp<JavaBBinderExt>::make(env, obj);
    {
        AutoMutex lock(mLock);
        if (sp<JavaBBinderExt> b2 = mBinder.promote()) {
            return b2;
        }
        mBinder = b;
    }
    return b;
}

构造在锁外执行,因为构造可能触发 GC;锁内二次 promote 防止两个线程并发创建两个 native wrapper。若另一个线程已经胜出,新构造对象立即被释放。

2.3 JavaBBinderExt ​

JavaBBinderExt 持有 JVM 指针和 Java Binder GlobalRef。析构时删除 GlobalRef;因此 native wrapper 的强生命周期必须覆盖所有可能的 JNI 回调,不能只保存 Java local reference。

3. Native到Java ​

3.1 本地Binder ​

源码文件:frameworks/base/core/jni/android_util_Binder.cpp

cpp
jobject javaObjectForIBinder(
        JNIEnv* env, const sp<IBinder>& val) {
    if (val == nullptr) return nullptr;
    if (val->checkSubclass(
            JavaBBinderBase::getExtSubclassID())) {
        return static_cast<JavaBBinderExt*>(
                val.get())->object();
    }
    ...
}

如果 native 对象本来由 Java Binder 创建,直接返回原 Java object,不创建 BinderProxy;这是 Java 本地对象身份保持的关键。

3.2 远程Binder ​

cpp
BinderProxyNativeData* nativeData =
        new BinderProxyNativeData;
nativeData->mOrgue =
        sp<DeathRecipientList>::make();
nativeData->mFrozenStateChangeCallbackList =
        sp<FrozenStateChangeCallbackList>::make();
nativeData->mObject = val;

jobject object = env->CallStaticObjectMethod(
        gBinderProxyOffsets.mClass,
        gBinderProxyOffsets.mGetInstance,
        (jlong)nativeData, (jlong)val.get());

远程对象创建 BinderProxyNativeData,其中强持有 native IBinder、death recipient list 和 frozen callback list,再交给 Java BinderProxy.getInstance()。若并发线程已经创建实际 proxy,新 nativeData 会被删除;Java proxy 只保留胜出者的 nativeData。

3.3 对象标记 ​

tryTagObject() 给 native IBinder 的弱控制块设置 Java proxy tag,帮助发现多个 Java nativeData 争用同一 native object。tag 失败可能只是另一个并发 proxy 已经胜出,不自动表示 Binder 事务失败。

4. 事务回调 ​

4.1 JavaBBinderExt ​

cpp
status_t JavaBBinderExt::onTransact(
        uint32_t code, const Parcel& data,
        Parcel* reply, uint32_t flags) {
    JNIEnv* env = javavm_to_jnienv(mVM);
    jboolean res = env->CallBooleanMethod(
            mObject, gBinderOffsets.mExecTransact,
            code, (jlong)&data, (jlong)reply, flags);
    return res != JNI_FALSE ? NO_ERROR
                            : UNKNOWN_TRANSACTION;
}

native Binder 线程收到事务后,JNI 调用 Java execTransact;Java 侧负责 Parcel 包装、calling UID/work source、observer、异常和回收,JNI 再把 boolean 转成 native status。

4.2 异常回流 ​

若 Java 抛出异常,JNI 取得 throwable,调用 binder_report_exception(),并把结果变成 JNI false/错误状态。oneway 调用没有 reply,异常不能编码给发送方,只能记录和报告。

5. 回调桥接 ​

5.1 DeathRecipient ​

cpp
void JavaDeathRecipient::binderDied(
        const wp<IBinder>& who) {
    JNIEnv* env = javavm_to_jnienv(mVM);
    jobject binderProxy =
            javaObjectForIBinder(env, who.promote());
    jobject recipient =
            env->NewLocalRef(mRecipientWeak);
    if (recipient == nullptr) return;
    env->CallVoidMethod(recipient,
            gBinderProxyOffsets.mSendDeathNotice,
            binderProxy);
}

native recipient 列表用 weak Java references;如果 Java recipient 已 GC,死亡通知会被丢弃并记录 warning。Java BinderProxy 的强 list 和 native weak callback 必须共同存在才能稳定收信。

5.2 Frozen回调 ​

JavaFrozenStateChangeCallback 用类似 weak callback 机制调用 Java BinderProxy 静态分发方法;事件可能合并,回调异常通过 binder_report_exception() 处理。

5.3 Proxy计数 ​

JNI 把 native BpBinder 的 warning/limit callback 转到 BinderInternal.binderProxyLimitCallbackFromNative(),再由 Java Handler 投递。native callback 线程不直接运行用户 listener。

6. 资源边界 ​

6.1 GlobalRef ​

JavaBBinderExt 的 GlobalRef 由 native wrapper 析构释放;BinderProxyNativeData 的 native IBinder 和 callback lists 由 NativeAllocationRegistry 生命周期释放。Java proxy map 弱引用清理不等于 nativeData 立即释放,必须等待 proxy 的 native allocation finalizer。

6.2 注册顺序 ​

JNI 注册必须先缓存 class/method/field offset,再允许 Java Binder/BinderProxy 调用 native 方法。启动阶段 offset 获取失败属于初始化错误,不应在业务事务中静默恢复。

7. 测试边界 ​

7.1 Java对象转换 ​

源码文件:frameworks/base/core/tests/coretests/src/android/os/ParcelTest.java

Binder 写入/读取测试间接覆盖 ibinderForJavaObject 与 javaObjectForIBinder 的对象身份,但不直接断言所有 holder 竞态。

7.2 死亡桥接 ​

源码文件:frameworks/base/core/tests/coretests/src/android/os/BinderDeathRecipientTest.java

测试注册 Java DeathRecipient、终止远端进程并等待回调,覆盖 native recipient 到 Java callback 的主线;不能证明 recipient GC 后仍然一定收到通知,因为源码明确允许 weak recipient 已被回收时丢弃通知。

7.3 可执行阅读 ​

bash
rg -n "JavaBBinderHolder|JavaBBinderExt|javaObjectForIBinder|ibinderForJavaObject" \
  frameworks/base/core/jni/android_util_Binder.cpp

rg -n "execTransact|gBinderOffsets|gBinderProxyOffsets|JNINativeMethod" \
  frameworks/base/core/jni/android_util_Binder.cpp

rg -n "BinderDeathRecipientTest|writeStrongBinder|readStrongBinder" \
  frameworks/base/core/tests/coretests/src/android/os

排查 Java Binder 转换问题时,先区分本地 Java Binder、远程 BinderProxy 和 nativeData ownership,再查看 JNI offset、GlobalRef、recipient weak reference 与 NativeAllocationRegistry;不要只在 Java 层看到一个 non-null IBinder 就断言 native wrapper 没有重复。