LeakCanary原理 弱引用与垃圾回收 强引用 软引用 弱引用 虚引用

本文介绍了LeakCanary如何通过检测Activity、Fragment等对象的生命周期来预防内存泄漏,重点讲解了弱引用、强引用、软引用和虚引用的区别及在内存优化中的作用,以及如何避免单例、静态变量和非静态内部类导致的内存泄漏问题。
摘要由CSDN通过智能技术生成

LeakCanary

LeakCanary 通过 hook Android 的生命周期来自动检测 Activity 和 Fragment 何时被销毁,何时应该被垃圾回收,这些被 destroy 的对象被传递给 ObjectWatcher,ObjectWatcher 持有对它们的弱引用

检测对象类型

  • 已销毁的 Activity 实例
  • 销毁的 Fragment 实例
  • 销毁的 Fragment View 实例
  • 已清除的 ViewModel实例

弱引用与垃圾回收

弱引用(WeakReference)可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收器回收,虚拟机就会把这个弱引用加入到与之关联的引用队列中,我们可以用此特性来检查一个对象是否被垃圾回收器回收成功
在这里插入图片描述

强引用

-般的obiect obj= new Object0),就属于强引用。在任何情况下,只有有强引用关联(与根可达)还在,垃圾回收器就永远不会回收掉被引用的对象。

软引用 SoftReference

  • 一些有用但是并非必需,用软引用关联的对象,系统将要发生内存溢出(0uyOfMemory)之前,这些对象就会被回收(如果这次回收后还是没有足够的空间,才会抛出内存溢出)。
    参见代码:
    VM参数-Xms10m-Xmx10m -XX:+PrintGc

例如,一个程序用来处理用户提供的图片。如果将所有图片读入内存,这样虽然可以很快的打开图片,但内存空间使用巨大,一些佳用较少的图片浪费内存空间,需要手动从内存中移除。如果每次打开图片都从磁盘文件中读取到内存再显示出来,虽然内存占用较少,但一些经常使用的图片每次打开都要访问磁盘,代价巨大。这个时候就可以用软引用构建缓存。

弱引用WeakReference

  • 一些有用(程度比软引用更低)但是并非必需,用弱引用关联的对象,只能生存到下一次垃圾回收之前,GC发生时,不管内存够不够,都会被回收。
  • 当一个对象仅仅被WeakReference(弱引用)指向,而没有任何其他strong reference(强引用)指向的时候,如果这时GC运行,那么这个对象就会被回收,不论当前的内存空间是否足够,这个对象都会被回收。
  • 注意:软引用 SoftReference和弱引用 WeakReference,可以用在内存资源紧张的情况下以及创建不是很重要的数据缓存。当系统内存不足的时候,缓存中的内容是可以被释放的。
  • 实际运用(WeakHashap、ThreadLocal)

GC回收后,弱引用不存在代码示例:

fun main(){
    val referenceQueue = ReferenceQueue<Any?>()
    var obj:Any? = Object()
    val weakReference = WeakReference(obj, referenceQueue)
    println("before GC:${weakReference.get()}")
    obj = null
    System.gc()
    Thread.sleep(1000)
    println("after GC:${weakReference.get()}")
}

虚引用

  • 幽灵引用,最弱(随时会被回收掉)
  • 垃圾回收的时候收到一个通知,就是为了监控垃圾回收器是否正常工作。

防止内存泄漏

单例导致内存泄露

为了避免这样单例导致内存泄露,我们可以将context参数改为全局的上下文

fun appSettings(context:Context){
    val applicationContext = context.applicationContext
}

静态变量导致内存泄漏

静态变量存储在方法区,它的生命周期从类加载开始,到整个进程结束。一旦静态变量初始化后,它所持有的引用只有等到进程结束才会释放。 比如下面这样的情况,在Activity中为了避免重复的创建info,将sInfo作为静态变量。

非静态内部类导致内存泄露

非静态内部类(包括匿名内部类)默认就会持有外部类的引用,当非静态内部类对象的生命周期比外部类对象的生命周期长时,就会导致内存泄露。非静态内部类导致的内存泄露在Android开发中有一种典型的场景就是使用Handler,很多开发者在使用Handler是这样写的。

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学知识拯救世界

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值