Android内存泄漏

总结内存泄露的相关知识点,以面试题的形式进行列举。

链接:https://blog.csdn.net/feather_wch/article/details/78289202

内存泄露汇总

版本:2018/8/10-1


内存泄露

1、内存泄露是什么?

  1. 分配的内存在使用后并没有释放,而导致内存一直被占用,直到结束
  2. 危害:持续的内存泄漏会导致可用内存越来越少,最终导致内存溢出(out of memory)

2、内存溢出是什么?

  1. OOM(Out of Memory),app所占的堆内存超过了系统规定的最大值HeapSize就会出现内存溢出导致应用崩溃

3、强引用(Strong reference)是什么

A a = new A()强引用本身存在栈内存中(其指向的A对象存储在堆中),不会被GC回收GC回收的是堆内存中的数据。

4、软引用

  1. 不具有强引用,当虚拟机内存不足时,会被回收。
  2. 适合做网页缓存、图片缓存等。
A a = new A();
SoftReference<A> srA = new SoftReference<A>(a);

5、弱引用

  1. 无论内存是否充足,只具有弱引用的对象都会立即回收。
A a = new A();
WeakReference<A> wrA = new WeakReference<A>(a);

6、虚引用(Phantom Reference)

  1. 只有虚引用的对象任何时候都会被回收。

7、强、软、弱、虚引用总结图
强、软、弱、虚引用总结图

8、查找内存泄露的几个关键点

  1. app上限制的heapsize是多少。
  2. 什么情况会导致无法GC
  3. 怎么复现哪个界面内存泄露

9、如何知道app上限值heapSize

//1. 获取`ActivityMnager`
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
//2. 获取heapSize
int heapSize = manager.getMemoryClass();
//3. 最大的heapSize
int maxHeapSize = manager.getLargeMemoryClass(); //AndroidManifest.xml中 android:largeHeap="true"

android:largeHeap="true"能将heapSize增大两到三倍,但并不是本质的解决OOM的方法

10、什么情况会导致无法GC

  1. 对象依旧持有引用,因此不会被GC

11、如何判断哪个界面导致内存泄露?如何定位?

  1. 利用LeakCanary
  2. 通过Android Studio 3.0Profiler

12、如何避免内存泄露

生命周期Activity长的类不要去强引用Activity

内存泄露常见场景(9种)

13、内存泄露常见场景有哪些

  1. 非静态内部类
  2. 静态类
  3. 静态变量
  4. WebView
  5. HandlerThread
  6. Bitmap
  7. 集合
  8. 动画
  9. 资源释放

非静态内部类

14、非静态的内部类会持有外部类的隐式引用

  1. 非静态内部类、匿名类:非静态的匿名类会持有外部类的一个隐式引用。
  2. Adpater、Handler和Runnable等会持有Activity的引用)
  3. 解决办法:内部类请用static变成静态内部类

15、Handler导致的内存泄露

  1. Runnable对象持有了Activity的强引用。
  2. Handler持有Activity的强引用。
//静态内部类:Handler
private static class MyHandler extends Handler{
    //1-弱引用持有Activity,可以被GC回收
    private WeakReference<ImageViewActivity> mActivityWeakReference;
    //2-Handler初始化,持有Activity弱引用
    public MyHandler(ImageViewActivity activity){
        mActivityWeakReference = new WeakReference<ImageViewActivity>(activity);
    }
    //3-用activity去调用一些业务逻辑的方法
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        //4-获取到Activity, 执行业务逻辑
        ImageViewActivity imageViewActivity = mActivityWeakReference.get();
        if(imageViewActivity != null){
            imageViewActivity.doSth();
        }
    }
}
private static Runnable myRunnable = new Runnable() {
    @Override
    public void run() {
        //TODO 业务逻辑
    }
};
//Activity中使用
MyHandler myHandler = new MyHandler(this);
myHandler.post(myRunnable);

OnDestory()中调用handler.removeCallbacksAndMessages(null);清除掉Handler中残留的任务,能提前GC的时间,而不是任务都执行完毕后,才进行GC

静态类

16、静态类持有Activity的引用

  1. 禁止静态类如Application、单例类、其他static类持有Activity的引用。
  2. 或者可以持有Activity的弱引用。

17、单例模式

  1. 单例模式的对象中的链表或者成员变量错误的持有了如:Activity的this指针,却没有及时释放会导致泄露,因为单例的特点是其生命周期和Applicaiton一致。
  2. 解决办法:避免该种场景,或者采用弱引用来解决该问题。

静态变量

18、静态变量导致内存泄露

如: Activity内部静态变量持有Activity的this等

WebView

19、WebView导致内存泄露的原因和解决办法

  1. AccessibilityStateChangeListener最终会持有WebView.mContext,也就是会持有Activity导致Activity无法释放。
  2. 该监听器是在ViewRootImpl的初始化中进行注册,在dispatchDetachedFromeWindow中进行反注册。
  3. 本质WebView的onDetahcedFromWindow并未正常执行完成,从而导致ViewRootImpldispatchDetachedFromeWindow不会执行。
if (mWebView != null) {
//1. WebView destory前将其从`父容器`中移除
   ViewParent parent = mWebView.getParent();
   if (parent != null) {
      ((ViewGroup) parent).removeView(mWebView);
   }
//2. WebView调用onDestory()方法
   mWebView.removeAllViews();
   mWebView.destroy();
   mWebView = null;
}

Bitmap

20、Bitmap导致的内存泄露

1.Bitmap没有用recycle()释放内存

HandlerThread

21、HandlerThread导致的内存泄露

. 关联ActivityHandlerThread生命周期过长,需要在Activity销毁方法中调用thread.getLooper().quit()

动画

22、无限循环动画导致内存泄露

  1. 属性动画不停止会导致内存泄漏:
  2. 无限循环动画会持有Activity的View,而View持有了Activity,最终导致泄露。
  3. 解决办法是: 在onDestory中调用animator.cancel()

资源释放

23、资源没有释放导致内存泄露

  1. IO
  2. Socket
  3. 数据库
  4. EventBus没有解除注册。
  5. 广播没有解除注册

集合

24、集合导致的内存泄露

  1. 静态集合持有对象的引用,导致引用无法释放,引起内存泄露。
  2. 解决办法: 在页面的onDestory中对集合进行清空。

工具

25、内存泄露检查常用工具

  1. LeakCanary:参考资料有教程
  2. Android Studio Porfile
  3. MAT
  4. adb shell的dumpsys指令

26、Android内存调试工具:dumpsys

dumpsys:是android自带的调试工具,能够查看内存的使用情况
1、通过adb shell dumpsys meminfo <packageName>来查看内存使用状况
2、打开Activity,运行指令后,可以看到ViewActivity的数量
3、关闭Activity,运行指令就可以看到关闭Acitivity后ViewActivity的数量
4、这样就可以简单判断出Acitivity是否出现内存泄漏

学习和参考资料

  1. LeakCanary使用教程
  2. (Android Studio 3.0)Android Profiler内存泄漏检查
  3. Android开发中常见的内存泄露案例
  4. WebView内存泄露解析
  5. Android内存泄露
  6. 译文:Android可能内存泄露的8种场景
  7. 手把手教你在Android Studio 3.0上分析内存泄漏

额外收获

  1. Layout Inspector已经替代了Hierarchy Viewer:用于查看布局层级
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Android内存泄露是指应用程序在使用完对象后,没有及时将其释放,导致这些对象无法被垃圾回收器回收,最终导致应用程序的内存占用不断增加,直至崩溃。以下是一些可能导致Android内存泄露的情况及解决方法: 1. 静态变量:如果在应用程序中使用了静态变量,并且这些变量引用了Activity或者Fragment等容器类,就可能导致内存泄露。解决方法是在Activity或者Fragment销毁时,将相关的静态变量设为null。 2. 匿名内部类:如果在应用程序中使用了匿名内部类,并且这些内部类引用了Activity或者Fragment等容器类,就可能导致内存泄露。解决方法是在Activity或者Fragment销毁时,将相关的匿名内部类引用设为null。 3. Handler:如果在应用程序中使用了Handler,并且这些Handler引用了Activity或者Fragment等容器类,就可能导致内存泄露。解决方法是在Activity或者Fragment销毁时,将相关的Handler引用设为null。 4. Bitmap对象:如果在应用程序中使用了Bitmap对象,并且没有及时释放,就可能导致内存泄露。解决方法是在使用完Bitmap对象后,调用recycle()方法释放内存。 5. 资源对象:如果在应用程序中使用了资源对象,并且没有及时释放,就可能导致内存泄露。解决方法是在使用完资源对象后,调用其对应的释放方法,比如close()。 希望以上这些解决方法可以帮助您避免Android内存泄露的问题。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

猎羽

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

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

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

打赏作者

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

抵扣说明:

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

余额充值