binder堆栈信息分析

这里详细说明下binder的调用堆栈,方便下次更快的定位到具体的代码

一堆栈信息跟踪

得出下以下观点,就是一个普通的堆栈信息打印
见BinderProxy.java的set方法:
throw new AssertionError("Binder ProxyMap has too many entries:......

1 中间没有对端的堆栈信息输出
2 也不会有native的调用堆栈信息
3 此堆栈信息是服务端打印的

具体看下每行的注释吧

E AndroidRuntime: FATAL EXCEPTION: Binder:1080_2
E AndroidRuntime: Process: com.xxx.xxx, PID: 1080
E AndroidRuntime: java.lang.AssertionError: Binder ProxyMap has too many entries: 20691 (total), 20691 (uncleared), 20691 (uncleared after GC). BinderProxy leak?//binderProxy:说明是客户端发送过来的binder泄漏了
E AndroidRuntime:         at android.os.BinderProxy$ProxyMap.set(BinderProxy.java:230)//对BinderProxy对象的缓存进行检查,发现太多了,报错
E AndroidRuntime:         at android.os.BinderProxy.getInstance(BinderProxy.java:432)//根据传来的参数new一个BinderProxy来
E AndroidRuntime:         at android.os.Parcel.nativeReadStrongBinder(Native Method)//困惑,居然能打印一行native(难道是javaObjectForIBinder用了啥牛叉的机制)
E AndroidRuntime:         at android.os.Parcel.readStrongBinder(Parcel.java:2483)//读取parcel中关于客户端的binde参数
E AndroidRuntime:         at com.xxx.xxx.object$Stub.onTransact(Iobject.java:121)//服务端重写的onTransact接口
E AndroidRuntime:         at android.os.Binder.execTransactInternal(Binder.java:1154)//
E AndroidRuntime:         at android.os.Binder.execTransact(Binder.java:1123)//1:服务端唤醒后的执行接口

所以这里的binder对象太多了,也就是客户端的那个binder太多了,没有释放,一般情况下,这个binder都是ams或servicemanager传过来的,唯一的,怎么会
太多了呢,这个一般不会泄漏,往往泄漏的是匿名的binder,比如通过callback传输一个binder给服务端以达到监听服务端的目的的时候
这个时候如果没有对这个客户端binder进行死亡监听,服务端又强引用了这个binder,客户端不停的启动的话,那就会泄漏

这个堆栈信息可以结合抓hprof文件来进行内存泄漏分析,hprof分析问题会解决的更全面,防止其他binder泄漏没有达到这个阈值,但仍泄漏的情况。

二:提供一套简化版的客户端和服务端,可以清晰的看到调用流程,而不是通过aidl来生成

简化版服务端

public class IPCService extends Service {
  
    private MyBinder mBinder = new MyBinder();
  
    private class MyBinder extends Binder {
        @Override
        protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
            switch (code) {
            case 0x001: {
                data.enforceInterface(DESCRIPTOR);
                int num = data.readInt();
                reply.writeNoException();
                reply.writeString("");
                return true;
            }
            }
            return super.onTransact(code, data, reply, flags);
        }
    }
  
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }
}

简化版客户端:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
  
    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceDisconnected(ComponentName name) {
            mIBinder = null;
        }
  
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mIBinder = service;
            
            
            android.os.Parcel _data = android.os.Parcel.obtain();
            android.os.Parcel _reply = android.os.Parcel.obtain();
            String _result = null;
            try {
                _data.writeInterfaceToken("IPCService");
                _data.writeInt(num);
                mIBinder.transact(0x01, _data, _reply, 0);
                _reply.readException();
                _result = _reply.readString();
            } catch (RemoteException e) {
                e.printStackTrace();
            } finally {
                _reply.recycle();
                _data.recycle();
            }
            
        }
    };
  
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
  
        // 绑定远程Service
        Intent service = new Intent("xxx.xxx.ipcserver");
        bindService(service, mConnection, BIND_AUTO_CREATE);
        
    }
 
}

三 带有callback的简化版服务端代码

对于我们刚才的打印堆栈信息中的情况
是需要一个callback接口由客户端传输过来一个binder的情况。
,也贴一个对应的简化版的服务端代码

即客户端定义了一个binder接口  IMyBinder通过一个callback接口传入到服务端,这时候服务端是要实例化这个binder的

@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
    
    case TRANSACTION_callback:
    {
        data.enforceInterface(descriptor);
        xxx.xxx.IMyBinder _arg0;
        _arg0 = xxx.xxx.IMyBinder.Stub.asInterface(data.readStrongBinder());
        this.callback(_arg0);
        reply.writeNoException();
        return true;
    }
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值