内存泄漏与内存溢出

1.内存泄漏(memory leak)申请了内存用完不释放,比如一共有1024M的内存,分配了521M的内存一直不回收,那么可以用的内存只有521M了,仿佛泄漏掉了一部分,通俗一点讲的话,就是(占着茅坑不拉屎)内存泄漏和内存溢出属于因果关系,因为泄漏导致内存溢出2.内存溢出(out of memory)OOM定义:App运行时占用的内存超过系统分配给改App的内存,就会出现内存溢出,递归,死循环图片加载(主要原因)1.超大图片(本地图片过大,服务器图片过大)2.大量加载图片并没有及时做回收或
摘要由CSDN通过智能技术生成
1.内存泄漏(memory leak)

指堆内存的泄漏,申请了内存用完不释放,而停留在堆内存中,比如一共可以用1024M的内存,分配了521M的内存,用完后一直不回收,那么可以用的内存只有521M了,仿佛泄漏掉了一部分,内存泄漏过多导致内存溢出

内存泄漏对程序的影响?

内存泄漏是造成应用程序OOM的主要原因之一。我们知道Android系统为每个应用程序分配的内存是有限的,而当一个应用中产生的内存泄漏比较多时,这就难免会导致应用所需要的内存超过系统分配的内存限额,这就造成了内存溢出从而导致应用Crash。

2.内存溢出(out of memory)OOM

定义:App运行时占用的内存超过系统分配给该App的内存,就会出现内存溢出,递归,死循环

申请内存时,没有足够的内存可以使用,通俗点讲,一个厕所3个坑,有两个占着茅坑不走的(内存泄漏)剩下最后一个坑,厕所表示接待压力很大,这时候一下来了两个人,坑位(内存)不够了,内存泄漏变成内存溢出

图片加载(主要原因)
1.超大图片(本地图片过大,服务器图片过大)
2.大量加载图片并没有及时做回收或销毁处理
3.Fragment大量加载,未做好回收,解除绑定的处理,就会大量的内存泄漏

导致内存泄漏的常见原因

1.循环过多或死循环,产生大量对象
2.静态集合类引起内存泄漏,因为静态集合的生命周期和JVM一致,所以静态集合引用的对象不能被释放,下面这个例子,list是静态的,只要JVM不停,那么obj也一直不释放
在这里插入图片描述
3.单例模式和静态集合导致内存泄漏的原因类似,因为单例的静态特性,它的生命周期的JVM的生命周期一样长,所以如果单例对象如果持有外部对象的引用,那么这个外部对象也不会被回收,那么就会造成内存泄漏

4.数据连接,IO,Socket连接等,没有close掉就不会被GC回收

5.内部类的对象被长期持有,那么内部类对象所属的外部类对象也不会被回收

6.内存中加载数据量过大,之前项目在一次上线的时候,应用启动不了,就是因为代码中会加载一个表中的数据到缓存(内存)中,测试环境有几百条数据,但是生产环境有几百万的数据

内存泄漏(耗时,引用)

定义:当activity销毁后,gc在回收该实例的时候,发现该activity的被其它对象持有引用,导致该activity不能被回收,出现内存泄漏。

因为内存泄漏是在堆内存中,所以对我们来说并不是可见的。通常我们可以借助MAT、LeakCanary等工具来检测应用程序是否存在内存泄漏。

MAT是一款强大的内存分析工具,功能繁多而复杂。

LeakCanary则是由Square开源的一款轻量级的第三方内存泄漏检测工具,当检测到程序中产生内存泄漏时,它将以最直观的方式告诉我们哪里产生了内存泄漏和导致谁泄漏了而不能被回收。只需要添加依赖,在application启动的时候,判断是否有leakcanary对该进程泄漏的监听,如果没有,在程序启动的时候安装leakcanary即可

常见案例

1.handler耗时引发的内存泄漏

当activity当中存在handler接收耗时的消息时,比如我们一般在网络请求的切换线程时,经常使用到的handler,假设消息还没有发送完成,但是该页面已经被关闭了,也就是activity已经执行了onDestory方法,当gc回收时,会出现该activity不能被回收的情况,导致内存泄漏。

解决方法:

当activity销毁的时候,调用handler的removeCallBacksAndMessage方法,移除消息任务,然后将handler对象及线程置空。

2.内部类引发的内存泄漏(当然handler或子线程一般也作为内部类使用)

因为java当中,内部类默认持有外部类的引用,当外部类销毁后,一旦该gc回收该实例,发现内部类持有它的引用而导致不能回收该实例,出现内存泄漏的情况。

解决方法:

将内部类改为静态内部类,因为静态内部类生命周期和应用一样长,所以当退出程序的时候会一同回收该实例,并不会影响外部类的回收

3.单例导致的内存泄漏

因为在使用单例的时候,经常会传入一个本类的上下文对象,而单例是静态的,生命周期和application一样长,当activity销毁的时候,该单例持有activity的引用导致其不能被回收,出现内存泄漏

解决方法:

在使用上下文的时候,传全局上下文

5.Bitmap对象不在使用时调用recycle()释放内存

6.Timer计时器,动画,因为这些涉及耗时问题,如果activity销毁,而该任务并未执行完成,会导致内存泄漏,所以一般在activity中如果使用到这些耗时任务,需要在activty销毁时,做对应处理,比如调用timer的cancel方法,或者动画的cancel方法并将对象置空

7.一些监听器的内存泄漏,比如说我们给edittext设置输入文字监听时,当监听到文字发生变化,我们通过获取变化后的文字执行了耗时任务(比如获取到edittext里的内容上传服务器),当耗时任务未执行完成activty销毁了,会引发内存泄漏,所以在onDestory时,取消注册,比如说edittext调用removeTextChangedListener方法

8.Rxjava的内存泄漏:因为Rxjava采用的是观察者模式,当请求到数据后会根据订阅关系将数据发送给订阅者,而如果这时订阅者已经销毁,就会出现引用该对象导致其不能被回收的情况,出现内存泄漏,rxjava2发布的时候也发现了这个问题,所以在回调当中新增加了onSubscribe回调,同时返回了一个disposable对象。可以通过判断disposable里的isDisposed来确定当前的订阅关系,如果订阅关系中的订阅者已经不存在且当前订阅关

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值