JavaBBinder
JavaBBinderExt 是 Java Binder 在 native 层的本地 Binder 包装。它继承内部 JavaBBinderBase,持有 JVM 和 Java Binder 的 GlobalRef,实现 descriptor、业务事务和稳定性/扩展属性,并在 native Binder 线程中调用 Java execTransact()。
本文面向已经读过 JNI层android_util_Binder、Binder基类详解 和 sp与wp智能指针 的读者。本文只讲 JavaBBinder 的 native 生命周期与事务回调,不重复 Java Binder API 或整体 JNI offset 注册。
1. 类型与所有权
1.1 内部基类
源码文件:frameworks/native/libs/binder/include_private/binder/internal/JavaBBinderBase.h
class JavaBBinderBase : public BBinder {
public:
static const void* getExtSubclassID();
virtual bool checkSubclass(const void* id) const = 0;
};基类只提供内部 subclass identification;JavaBBinderExt 继承它,javaObjectForIBinder() 可据此判断一个 native IBinder 是否本来由 Java Binder 创建。
1.2 Java GlobalRef
源码文件:frameworks/base/core/jni/android_util_Binder.cpp
JavaBBinderExt(JNIEnv* env, jobject object)
: mVM(jnienv_to_javavm(env)),
mObject(env->NewGlobalRef(object)) {}
virtual ~JavaBBinderExt() {
JNIEnv* env = javavm_to_jnienv(mVM);
env->DeleteGlobalRef(mObject);
}native 包装不能保存 JNI local reference,因为 Binder 事务可能由其他线程、很晚的时间到达;GlobalRef 让 Java Binder 在 native wrapper 存活期间保持可回调。析构时删除 GlobalRef,native weak/strong 生命周期结束后才释放 Java 根引用。
1.3 Holder弱缓存
Mutex mLock;
wp<JavaBBinderExt> mBinder;
bool mVintf = false;
bool mSetExtensionCalled = false;
bool mInheritRt = false;Java Binder 的 holder 保存 wp<JavaBBinderExt>,不是强引用。没有 native 使用者时 wrapper 可以销毁;下次需要把同一 Java Binder 转成 native 时,holder 会重新创建 wrapper,并把已记录的 stability/extension/scheduler 配置应用回去。
2. 属性与descriptor
2.1 延迟descriptor
const String16& JavaBBinderExt::getInterfaceDescriptor() const {
call_once(mPopulateDescriptor, [this] {
JNIEnv* env = javavm_to_jnienv(mVM);
jstring descriptor = (jstring)env->CallObjectMethod(
mObject, gBinderOffsets.mGetInterfaceDescriptor);
if (descriptor == nullptr) return;
const jchar* chars = env->GetStringChars(descriptor, nullptr);
mDescriptor = String16(
reinterpret_cast<const char16_t*>(chars),
env->GetStringLength(descriptor));
env->ReleaseStringChars(descriptor, chars);
});
return mDescriptor;
}descriptor 第一次被 native 查询时才回调 Java,并由 once_flag 缓存。返回空字符串与 JNI 异常/对象销毁是不同边界;调用者应检查 descriptor 是否可用,而不是反复假设每次都会重新读取。
2.2 稳定性与扩展
holder 的 markVintf()、forceDowngradeToSystemStability()、setExtension() 和 setInheritRt() 在锁内更新状态;如果 wrapper 已存在,立即应用到 JavaBBinderExt,否则等下次创建时应用。属性必须在 Binder 被发出或参与跨进程传输前完成。
3. 事务回调
3.1 onTransact
源码文件:frameworks/base/core/jni/android_util_Binder.cpp
相关函数:JavaBBinderExt::onTransact()
status_t JavaBBinderExt::onTransact(
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags) {
JNIEnv* env = javavm_to_jnienv(mVM);
LOG_ALWAYS_FATAL_IF(env == nullptr,
"env null. Attach JVM?");
IPCThreadState* state = IPCThreadState::self();
const int32_t strictBefore =
state->getStrictModePolicy();
jboolean res = env->CallBooleanMethod(
mObject, gBinderOffsets.mExecTransact,
code, reinterpret_cast<jlong>(&data),
reinterpret_cast<jlong>(reply), flags);
...
return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;
}native Binder 线程需要有 JNIEnv;没有 attach JVM 是进程级错误。native 把 Parcel 地址和 flags 传给 Java execTransact,Java 执行身份、observer、异常和 Parcel recycle,返回 boolean 后再转为 native status。
3.2 StrictMode恢复
if (state->getStrictModePolicy() != strictBefore) {
set_dalvik_blockguard_policy(env, strictBefore);
}Binder underlying state 会恢复 native strict policy,但 Dalvik/Java BlockGuard 状态需要 JNI 层额外同步。否则一次 incoming transaction 修改的策略可能泄漏到下一次使用同一 Binder 线程。
3.3 系统属性命令
SYSPROPS_TRANSACTION 即使 Java execTransact 返回,也会额外调用 BBinder::onTransact() 的 native 实现。这是特殊协议命令,不能套成所有业务 code 都会双重分发。
4. 资源与竞态
4.1 构造竞态
Holder 在锁外构造 wrapper,因为构造可能触发 GC;两个线程可能同时构造,但锁内二次 promote 只保留一个,另一个通过 sp 析构释放 GlobalRef。构造期间不能把 holder mutex 传入会触发 Java/GC 的路径。
4.2 wrapper销毁
JavaBBinderExt 析构删除 GlobalRef;holder 的 Java Binder 仍可能存在,但 native wrapper 已不在。下一次 ibinderForJavaObject() 会重新创建 wrapper,不代表 Java Binder identity 改变。
4.3 Java异常
如果 Java execTransact 抛异常,JNI 取得 throwable 并调用 binder_report_exception(),返回 JNI false。同步异常由 Java Binder 写入 reply;oneway 没有同步 reply,只能记录/报告。
5. 测试边界
5.1 Java转换
源码文件:frameworks/base/core/tests/coretests/src/android/os/ParcelTest.java
Parcel Binder 写入/读取覆盖 Java Binder 与 native conversion 的主线,但不直接断言 holder 并发构造胜负。
5.2 远程事务
源码文件:frameworks/native/libs/binder/tests/binderLibTest.cpp
Native Binder 测试通过远程服务调用 Java/Native Binder 对象,覆盖事务、线程和死亡通知边界;不单独验证 Java StrictMode restore 或 descriptor lazy cache。
5.3 可执行阅读
rg -n "JavaBBinderBase|JavaBBinderExt|JavaBBinderHolder|GlobalRef|mBinder.promote" \
frameworks/base/core/jni/android_util_Binder.cpp \
frameworks/native/libs/binder/include_private/binder/internal/JavaBBinderBase.h
rg -n "execTransact|StrictMode|SYSPROPS_TRANSACTION|binder_report_exception" \
frameworks/base/core/jni/android_util_Binder.cpp
rg -n "writeStrongBinder|readStrongBinder|BinderDeath" \
frameworks/base/core/tests/coretests/src/android/os/ParcelTest.java \
frameworks/native/libs/binder/tests/binderLibTest.cpp排查 Java Binder 本地对象没有响应时,先确认 holder 是否能 promote/create wrapper,再检查 JNIEnv、descriptor、execTransact 和 StrictMode restore;不要只检查 Java Binder 对象仍然可达就断言 native wrapper仍然存在。
