javaObjectForIBinder
javaObjectForIBinder() 决定一个 native sp<IBinder> 在 Java 世界中的对象身份。若对象本来是当前 JVM 创建的 JavaBBinderExt,函数直接返回原 Java Binder;否则创建候选 BinderProxyNativeData,调用 Java BinderProxy.getInstance() 按 native 指针复用或创建 proxy,再处理竞争失败候选的释放。
本文承接 JNI层android_util_Binder、JavaBBinder 和 BinderProxy详解。本文只深挖 native→Java 转换的对象身份与 ownership,不重复 transact 和 death callback 业务。
1. 输入边界
源码文件:frameworks/base/core/jni/android_util_Binder.cpp
jobject javaObjectForIBinder(
JNIEnv* env, const sp<IBinder>& val) {
if (val == nullptr) return nullptr;
...
}输入使用 sp<IBinder>,函数执行期间 native 对象有强引用保护。null 映射为 Java null,不创建 holder 或 proxy。
2. 本地对象
2.1 子类识别
if (val->checkSubclass(
JavaBBinderBase::getExtSubclassID())) {
jobject object =
static_cast<JavaBBinderExt*>(
val.get())->object();
return object;
}checkSubclass() 使用内部稳定 ID 判断对象是否为 JavaBBinderExt,不是靠 descriptor 或 C++ RTTI 名称。命中后返回 wrapper 持有的原 Java GlobalRef 对象。
2.2 身份闭环
Java Binder 经 ibinderForJavaObject() 变成 JavaBBinderExt,再经本函数返回时仍是原 Java Binder,不创建 BinderProxy。这保证本地 Binder 往返 Parcel 后保持 Java 对象身份。
3. Proxy候选
3.1 NativeData内容
struct BinderProxyNativeData {
sp<IBinder> mObject;
sp<DeathRecipientList> mOrgue;
sp<FrozenStateChangeCallbackList>
mFrozenStateChangeCallbackList;
};nativeData 强持有目标 IBinder 以及两类回调列表。Java BinderProxy 的单个 long 字段指向这个聚合对象,由一个 NativeAllocationRegistry finalizer 统一释放。
3.2 创建候选
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());候选在进入 Java 前已经拥有完整 native 引用。Java getInstance() 负责决定该候选是否成为实际 proxy 的 nativeData。
4. Java仲裁
源码文件:frameworks/base/core/java/android/os/BinderProxy.java
private static BinderProxy getInstance(
long nativeData, long iBinder) {
synchronized (sProxyMap) {
BinderProxy result = sProxyMap.get(iBinder);
if (result != null) return result;
result = new BinderProxy(nativeData);
sRegistry.registerNativeAllocation(
result, nativeData);
sProxyMap.set(iBinder, result);
return result;
}
}key 是 native IBinder 指针,value 是 Java proxy 弱引用。锁保证同时只有一个活跃 proxy 成为正式对象;候选 nativeData 是否被接管,需要回到 native 比较实际字段。
5. Ownership收束
5.1 竞争结果
BinderProxyNativeData* actual =
getBPNativeData(env, object);
if (actual == nativeData) {
nativeData->tryTagObject();
} else {
delete nativeData;
}字段仍等于候选指针,说明新 Java proxy 接管了它;否则 Java 返回的是已有 proxy,当前候选必须删除。删除会释放其 sp<IBinder> 和 callback lists,避免并发转换泄漏 native 引用。
5.2 Java异常
如果 getInstance() 抛异常,它负责通过 free function 清理 nativeData;native 看到 pending exception 后直接返回 null,不能再次 delete,否则 double free。
5.3 对象tag
胜出候选调用 tryTagObject() 给 RefBase 控制块设置 Java proxy tag。并发旧 proxy 尚未 finalizer 时 tag 可能失败,这是一种诊断竞争,不影响返回 proxy 的功能。
6. 消费入口
该函数被 Parcel Binder 读取、ServiceManager context object、输入 token、SurfaceControl token、WindowManager token、死亡和 frozen callback 等多个 JNI 入口调用。所有消费者共享同一身份规则:JavaBBinder 回原对象,其他 IBinder 进 ProxyMap。
7. 测试边界
7.1 Parcel往返
源码文件:frameworks/base/core/tests/coretests/src/android/os/ParcelTest.java
测试写入/读取 Java Binder,并比较返回对象身份,覆盖本地 JavaBBinder 直返和远程 Binder proxy 转换的可观察结果;它不直接强制制造两个线程同时竞争 nativeData。
7.2 Proxy计数
BinderProxyCountingTest 验证 Java/native proxy 数和 UID 水位,但不证明每次转换是否命中同一 weak value 的具体 GC 时序。
7.3 可执行阅读
rg -n "javaObjectForIBinder|BinderProxyNativeData|getBPNativeData|tryTagObject" \
frameworks/base/core/jni/android_util_Binder.cpp
rg -n "getInstance|sProxyMap|registerNativeAllocation|mNativeData" \
frameworks/base/core/java/android/os/BinderProxy.java
rg -n "writeStrongBinder|readStrongBinder|BinderProxyCounting" \
frameworks/base/core/tests/coretests/src/android/os排查 native Binder 转 Java 出现重复对象或泄漏时,先确认是否是 JavaBBinder 本地直返,再检查 ProxyMap weak value、实际 mNativeData 是否接管候选、异常分支是否由 Java free function 清理;不能只按 descriptor 判断对象身份。
