Android BinderProxy leak 原理分析

1. 背景
项目正常压力测试,system_server crash导致系统重启。查看dropbox里面的system_server_crash trace,发现是因为系统检测到system_server 的 BinderProxy累计数量超过了android系统设置的20000,认为存在BinderProxy leak,抛出异常,最终导致system_server crash。

private static final int CRASH_AT_SIZE = 20_000;

07-27 19:14:19.587883 28713 29738 E AndroidRuntime: java.lang.AssertionError: Binder ProxyMap has too many entries: 21033 (total), 20593 (uncleared), 20480 (uncleared after GC). BinderProxy leak?
07-27 19:14:19.587883 28713 29738 E AndroidRuntime: 	at android.os.BinderProxy$ProxyMap.set(BinderProxy.java:230)
07-27 19:14:19.587883 28713 29738 E AndroidRuntime: 	at android.os.BinderProxy.getInstance(BinderProxy.java:432)
07-27 19:14:19.587883 28713 29738 E AndroidRuntime: 	at android.view.InputChannel.nativeGetToken(Native Method)
07-27 19:14:19.587883 28713 29738 E AndroidRuntime: 	at android.view.InputChannel.getToken(InputChannel.java:185)
07-27 19:14:19.587883 28713 29738 E AndroidRuntime: 	at com.android.server.wm.WindowState.openInputChannel(WindowState.java:2476)  
07-27 19:14:19.587883 28713 29738 E AndroidRuntime: 	at com.android.server.wm.WindowManagerService.addWindow(WindowManagerService.java:1626)
07-27 19:14:19.587883 28713 29738 E AndroidRuntime: 	at com.android.server.wm.Session.addToDisplayAsUser(Session.java:176)
07-27 19:14:19.587883 28713 29738 E AndroidRuntime: 	at android.view.IWindowSession$Stub.onTransact(IWindowSession.java:679)
07-27 19:14:19.587883 28713 29738 E AndroidRuntime: 	at com.android.server.wm.Session.onTransact(Session.java:139)
07-27 19:14:19.587883 28713 29738 E AndroidRuntime: 	at android.os.Binder.execTransactInternal(Binder.java:1154)
07-27 19:14:19.587883 28713 29738 E AndroidRuntime: 	at android.os.Binder.execTransact(Binder.java:1123)

2. bug分析
通过打印的堆栈信息可以知道: at android.os.BinderProxy$ProxyMap.set(BinderProxy.java:230) 是BinderProxy的230行出现的异常,找到对应的源码如下:

        void set(long key, @NonNull BinderProxy value) {
   
            int myHash = hash(key);
            ArrayList<WeakReference<BinderProxy>> valueArray = mMainIndexValues[myHash];
            if (valueArray == null) {
   
                valueArray = mMainIndexValues[myHash] = new ArrayList<>();
                mMainIndexKeys[myHash] = new Long[1];
            }
            int size = valueArray.size();
            WeakReference<BinderProxy> newWr = new WeakReference<>(value);
            // First look for a cleared reference.
            // This ensures that ArrayList size is bounded by the maximum occupancy of
            // that bucket.
            for (int i = 0; i < size; ++i) {
   
                if (valueArray.get(i).get() == null) {
   
                    valueArray.set(i, newWr);
                    Long[] keyArray = mMainIndexKeys[myHash];
                    keyArray[i] = key;
                    if (i < size - 1) {
   
                        // "Randomly" check one of the remaining entries in [i+1, size), so that
                        // needlessly long buckets are eventually pruned.
                        int rnd = Math.floorMod(++mRandom, size - (i + 1));
                        
  • 46
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值