Android 使用LeakCanary检测内存泄漏,分析原因

内存泄漏是指无用对象(不再使用的对象)持续占有内存或无用对象的内存得不到及时释放,从而造成内存空间的浪费称为内存泄漏。

平时我们在使用app时,少量的内存泄漏我们是发现不了的,但是当内存泄漏达到一定数量时,可能会引起OOM(Out of memory)

我们可以借助工具LeakCanary来检测内测泄漏

首先在项目build.gradle中引入LeakCanary库

  //https://github.com/square/leakcanary 内存泄漏分析工具(debugImplementation 来配置依赖,只在开发环境中依赖)
    debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.12'

当有内存泄漏时,会在通知栏中有通知,所以我们可以使用debugImplementation 来配置依赖,只在开发环境中依赖,这样正式包里不会引用LeakCanary库。

使用LeakCanary 2.0以上版本,无需做任何配置,引入库后就会自动检测内存泄漏

单例模式导致的内存泄漏

创建一个单例

public class Singleton {
    private static Singleton sInstance;
    private Context mContext;
 
    private Singleton(Context context) {
        this.mContext = context;
    }
 
    public static Singleton getInstance(Context context) {
        if (sInstance == null) {
            sInstance = new Singleton(context);
        }
        return sInstance;
    }
    public void test(){
        mContext.getContentResolver();
    }
}

在Activity中执行

public class TestLeakActivity extends Activity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test_leak);
        Singleton.getInstance(this).test();
    }
}

执行完单例之后看一下leakcanary

LeakCanary: 1 APPLICATION LEAKS
LeakCanary: ┬───
LeakCanary: │ GC Root: Local variable in native code
LeakCanary: │ ...            
LeakCanary: ├─ com.example.myapplication.Singleton instance
LeakCanary: │    Leaking: UNKNOWN
LeakCanary: │    Retaining 112915 bytes in 1674 objects
LeakCanary: │    mContext instance of com.example.myapplication.TestLeakActivity with mDestroyed = true
LeakCanary: │    ↓ Singleton.mContext
LeakCanary: │                ~~~~~~~~
LeakCanary: ╰→ com.example.myapplication.TestLeakActivity instance
LeakCanary: ​     Leaking: YES (ObjectWatcher was watching this because com.example.myapplication.TestLeakActivity received
LeakCanary: ​     Activity#onDestroy() callback and Activity#mDestroyed is true)
LeakCanary: ​     Retaining 112903 bytes in 1673 objects
LeakCanary: ​     key = 297d72a4-5e9d-41bf-baba-6856105c73f0
LeakCanary: ​     watchDurationMillis = 5176
LeakCanary: ​     retainedDurationMillis = 139
LeakCanary: ​     mApplication instance of com.example.myapplication.MyApplication
LeakCanary: ​     mBase instance of android.app.ContextImpl, not wrapping known Android context
LeakCanary: ====================================
LeakCanary: 0 LIBRARY LEAKS

发现UNKNOW 出现地方为Singleton中的mContext,说明当前的mContext可能没有释放掉,但是后续又看到YES说明当前确实没有释放掉

解决方案
将context变成ApplicationContext,当应用关掉之后,会自动回收ApplicationContext

 private Singleton(Context context) {
        this.mContext = context.getApplicationContext();
 }
  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值