Binder的异常处理机制(快递包裹版)
可以把Android的跨进程通信(Binder)想象成收发快递,服务端是发货方,客户端是收货方:
📦 服务端处理流程(发货方)
-
业务出错(比如示例中的
throw new RuntimeException)- 就像打包时发现货物破损,必须处理这个错误
-
包裹打包站(execTransactInternal)
-
这里有两个大纸箱:
- RemoteException(快递本身的问题)
- RuntimeException(包装过程的问题)
-
如果是"闪送件"(oneway调用):直接贴错误标签,不退回包裹
-
如果是普通件:把错误信息压缩成"错误代码+文字说明"(如
code=EX_ILLEGAL_STATE,"testexception")
-
-
错误信息压缩(writeException)
- 不邮寄整个破损货物(不传异常对象)
- 用数字代码表示错误类型(比如用5代表"空指针异常")
- 附加简要文字说明(比如"包裹地址填写错误")
-
终极检查站(JNI层)
- 如果还有未处理的错误,直接打印红色警告:"对方收到了一包损坏的货物!"
📭 客户端处理流程(收货方)
-
拆包裹时检查(readException)
- 先看包裹上的错误代码(比如数字5)
- 再读文字说明("testexception")
-
还原错误现场(createException)
- 根据代码还原对应的异常类型(比如5→
NullPointerException) - 把文字说明塞进新异常里,就像重新包装破损的货物
- 根据代码还原对应的异常类型(比如5→
-
抛出还原的异常
- 最终客户端会收到一个"空指针异常,原因:testexception"
🔑 关键设计点
- 轻量化传输:只传错误代码+文字,不传整个异常对象(就像只传快递单号不传包裹本身)
- 异常类型白名单:只处理系统预定义的异常类型(类似快递公司只受理特定类型的包裹)
- oneway特殊处理:单向快递(不要求回执)直接丢弃错误,避免等待超时
- 跨进程限制:不同进程的类加载器不同,无法直接传输自定义异常(就像A公司的包装盒B公司不认识)
💡 举个例子
服务端抛出一个new RuntimeException("电池漏液"):
- 转换成
code=EX_ILLEGAL_STATE+ "电池漏液" - 客户端收到后还原为
IllegalStateException("电池漏液")
这种设计既保证了跨进程安全,又避免了传输复杂的对象结构,就像快递公司用标准化流程处理各种问题包裹。