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
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 方法注册
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
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缓存
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
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
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
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
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 可执行阅读
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 没有重复。
