LeakCanary
普通的观测内存泄漏:主动调用runtime.gc,然后看finalized是否被调用
如何观察到所有Activity的onDestory
通过在application中注册registerActivityLifeCycleCallbacks()获取activity的生命周期
通过注册Activity的LifeCycle,监测到activity的onDestroy状态,在这时RefWatcher.watch(activity)
fragment:activity.getFragmentManager.registerFragmentLifeCycleCallbacks
如何判断Activity泄漏了
记录onDestory的时间点
生成一个uuid作为key
把key加入集合,这个集合就是观察名单
创建包装类KeyedWeakRefrence把key和activity放入,这是一个弱引用
弱引用:如果弱引用包裹的对象只在弱引用中被引用,gc时会直接回收
软引用:比弱引用更强一点,在接近oom时才会被回收,但在Android中,只要gc就会被回收
虚引用:get永远为null,参数里有ReferenceQueue,在gc前会把回收的对象添加进这个queue,用来判断对象是否被回收,比finalize可靠
创建excuter执行检测方法
excuter判断当前是否在主线程,如果是Looper.myQueue.addIdleHandler,这个会在主线程空闲时间执行,执行了说明生命周期正常执行完毕
然后切换子线程执行检测方法ensureGone
对弱引用对象的ReferenceQueue进行轮询取出并对比是否有传入的弱引用对象,如果有,说明已经正确的回收了,把key从集合中移除
如果轮询完怀疑名单中还有对象,主动gc,再次进行上一步
Runtime.getRuntime.gc
try{
Thread.sleep(100)
} catch (InterreptedException e) {
throw new AssertionError()
}
System.runFinalization()
如果还是不成功把收集heap信息组成HeapDump对象进行分析
如何收集分析内存泄漏信息
如何收集heap信息:Debug.dumpHprofData
开启服务进行处理
如何分析:使用IntentService,从堆中找到弱引用的对象,通过key判断
找到对象的引用路径,通过第三方库:haha
2.0变化
初始化操作没有了,放在了provider里
支持androidx下的fragment
支持rootview和service检测
rootview:
如何获取:引入第三方库Curtains,原理是反射WindowManagerGlobal
如何检测:rootView.addOnAttachStateChangeListener
service:
如何获取:反射ActivityThread替换Handler得到service销毁的消息
在1.0中Looper.myQueue.addIdleHandler的地方改为延迟5s
分析堆内存自己写了没用haha