内存泄漏

本文深入解析Java中的内存泄漏问题,包括内存泄漏的概念、常见原因及解决方案。探讨了单例、Handler、非静态内部类、线程、资源未关闭、系统服务、监听器未注销和动画等场景下内存泄漏的具体实例,并提供了相应的解决策略。

内存泄漏:在基于Java的运行中,内存泄漏是一种编程错误,它会导致应用程序对已经不需要再使用对象的引用。所以,无法回收该系统给该对象分配的内存。最终导致OOM(OutOfMemoryError 内存泄漏) 崩溃。

简单来说就是:一些对象有着有限的生命周期。当这些对象所要做的事情完成了,我们希望他们会被回收掉。但是如果有一系列对这个对象的引用,那么在我们期待这个对象生命周期结束的时候被收回的时候,它是不会被回收的。它还会占用内存,这就造成了内存泄露。持续累加,内存很快被耗尽。

内存泄漏出现的一些实例:

1.单例–生命周期

分析:因为单例的生命周期和应用程序一样,如果单例对象持有了某个不再需要

的对象的引用,(比如 Activity 的 context),那么这个 Activty 在单例没有被

释放前将不会被释放。

解决:我们可以让单例的引用为 Application 的 context

2.Handler

我们经常会在 activity 中这样使用 handler:

class MyHandler extends Handler{

}//使用

MyHandler mHandler=new MyHandler(this);

分析:由于 myHandler 是 Handler 的非静态匿名内部类的实例,所以它持有外部

类 Activity 的引用,Looper 线程不断轮询处理消息,Activity 退出时如果消息队列

里还有未处理的消息,消息队列的 Message 持有 mHandler 的引用,mHandler 又

持有 Activity 的引用,所以导致 Activity 无法及时被 GC 回收。从而造成内存泄漏

解决方法:

1.创建静态 Handler 的匿名内部类 static class MyHandler extends Handler

2.把对 Handler 持有的对象的使用弱引用 WeakReference context;

  1. 在 Activity 销 毁 时 移 除 消 息 队 列 中 的 任 务 或 消

息 handler.removeCallbacksAndMessages(null);取消所有的消息的处理

3.非静态内部类创建静态实例

分析:非静态内部类可以自由使用外部类的所有变量和方法,非静态内部类,它

默认持有外部类的引用,此时如果在外部类创建静态 static 的内部类的实例,或

是声明为 static 静态成员变量,这样就导致内部类的生命周期和应用程序一样长,

导致 Activity 无法正常销毁。

解决方法:将非静态内部类转为静态内部类,这样就不会隐式持有外部类。

4.线程造成的内存泄漏

分析:我们常用的异步任务(如:AsyncTask)和 Runnable 都是匿名内部类,所以它

们对当前的 Activity 都有一个隐式引用,若 Activity 销毁,但是线程的任务还没有

完成,就会造成 Activity 的 gc 无法回收。

解决方法:

1.使用静态内部类 将 Runnable 内部类、AsyncTask 内部类声明为静态。

2.销毁时取消相应的任务。

5.资源未关闭

BroadcastReceiver、File、Cursor、Stream、Bitmap 及时关闭和注销、否则不会

被回收造成内存泄漏。

6.系统服务、监听器未注销/移除

有一些系统服务或监听器在不需要使用的时候再及时移除或注销

7.动画

对于有一些属性动画,属性为无限循环,这时候我们可以在 onStop 中停止动画。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值