内存走漏

内存不需要运用时,但是无法开释归还给系统,关于目标的引证无法及时开释,简单一句话,短生命周期的目标被长生命周期的目标持有了

常见的内存走漏

  1. 被static修饰的变量的生命周期和应用程序的一样长,非静态内部类的目标赋值给了静态引证,(非静态的内部类会默许持有外部类的引证,导致外部类无法开释)
  2. 资源运用后没有关闭:文件流,数据库等
  3. 匿名内部类(给静态变量设置监听时,因为匿名内部类会持有Activity引证,static又持有匿名内部类引证)
  4. Handler 内存走漏

初始化

在1.x 版别之中需要在application中手动初始化

在2.x 版别之中不需要自己初始化,他自己注册了一个contentProvider

contentProvider在application创立之后,在activity创立之前被创立,因而能够在contentProvider的oncreate办法中获取到applicationContext目标

测验发现其履行顺序

ContentProvider->onCreate() Application->onCreate() Activity->onCreate()

调查源码发现

ActivityThread中,创立Application目标之后会调用installContentProviders()安装归于当时进程,因而,一些需要在Application中初始化的操作能够放到ContentProvider中处理,这是一个很奇妙的解耦办法

这种办法尽管简化了开发人员的代码编写,但是对应用的发动冷发动速度会造成一定的影响,在编写SDK的时分还是应该提供初始化办法(有的时分能够推迟初始化来达到提高发动速度的目的)

至于为什么LeakCanary设置成这样,因为leakCanary只是在开发阶段运用的工具,在后续的release版别并不会参加,并不会造成影响

LeakCanary浅析

原理

Android里边常见的资源目标都有生命周期的回调,在某个目标不在需要回调时分会履行毁掉的生命周期回调(例如Activity的onDestroy),履行之后阐明咱们的 activity 目标是需要收回的。

LeakCanary 便是在onDestroy的时分注册回调,把activity目标运用弱引证目标包装,并对该activity 生成一个仅有id,

why 用弱引证 ,因为弱引证里边包装的目标在垃圾收回之前 弱引证目标会被参加到一个引证行列ReferenceQueue中, 然后以<id,WeakReference<activity>>的形式参加到一个map中(这个map能够当作一个可置疑目标,置疑这个目标有可能会发生内存走漏),之后手动调用GC ,GC之后去ReferenceQueue找当时id 所对应的WeakReference是否存在,如果存在,则阐明被收回了,并把map中的置疑目标移除,否则,则阐明发生了内存走漏,之后导出堆文件进行剖析

源码浅析

进入到MainProcessAppWatcherInstaller能够发现只完成了一个空壳的ContentProvider,只在oncreate办法里边进行了初始化工作

LeakCanary浅析

进入ManualyInstall办法中能够看到install一共有四个完成类,也便是能够监控Activity/Fragment/View/Service的内存走漏

LeakCanary浅析

以activity为例,点进去能够看到注册了回调,registerActivityLifecycleCallBacks 注册之后能够监听所有的activity的生命周期回调

LeakCanary浅析

进入到expectWeaklyReachable 办法

LeakCanary浅析

符号1 处把引证行列清空

符号2处 包装activity 和key 的弱引证并在符号3 处参加map中(置疑走漏的目标)

进入 moveToRetained

这儿的executor 便是把一个runnable 发送到了主线程的Looper中,并推迟5秒钟履行

LeakCanary浅析

之后又在子线程进入了checkRetainedObjects办法

LeakCanary浅析

LeakCanary浅析

之后自动调用GC ,并再次计算进行置疑目标的移除

此时计算出置疑数量之后在checkRetainedCount 办法中判别走漏数量是否达到阈值,默许为5,达到阈值才dump内存,否则给出一个告诉

dump通过Debug.dumpHprofData(heapDumpFile.absolutePath)来dump出 hprof文件,这个是AndroidSDK 自带的

之后LeakCanary会通过调用shark剖析gcroot的最短途径得出其走漏途径的trace,以前1.x版别用的剖析库是haha,传闻shark 剖析时间会大幅度减少