内存泄漏就是我们对某一内存空间的使用,使用完成后没有释放。

1. 资源释放问题

    长期保持某些资源,如 Context、Cursor、IO 流的引用,资源得不到释放 造成内存泄露。

2. 对象内存过大问题

    保存了多个耗用内存过大的对象,如 Bitmap、XML 文件等,造成内存超出限制。

3. static关键字的使用问题

    static 是 Java 中的一个关键字,当用它来修饰成员变量时,那么该变量就属于该类,而不是该类的实例。所以用 static 修饰的变量,它的生命周期是很长的,如果用它来引用一些资源耗费过多的实例(Context 的情况最多),这时就要谨慎对待了。如下

     public class ClassName { private static Context mContext; }

   以上的代码是很危险的,如果将 Activity 赋值到 mContext 的话。那么即使该 Activity 已经 onDestroy,但是由于仍有对象保存它的引用,因此该 Activity 依然不会被释放。

    针对 static 的解决方案

       1) 应该尽量避免 static 成员变量引用资源耗费过多的实例,比如 Context。

       2) Context尽量使用ApplicationContext,因为Application的Context的生命周期比较长,引用它不会出现内存泄露的问题。

       3) 使用 WeakReference 代替强引用. 比如可以使用 WeakReference<Context>  mContextRef;

4.集合类泄漏

       集合类如果只有添加元素的方法,而没有相应的删除机制导致内存被占用.

5.单例造成的内存泄漏

       由于单例的静态特性使得其生命周期和应用的生命周期一样长,所以如果使用不当就会造成内存泄漏.比如需要传入一个 context, 如果传入的是 application 的 context, 因为 application 的生命周期是整个应用的生命周期,所以不会有任何问题.如果传入的是 Activity 的 context, 当 Context 对应的 activity 退出时,由于该 Context 的引用被单例对象所持有,其生命周期等于整个应用的生命周期,所以当前 activity 退出时它的内存不会被回收,这就造成了内存泄漏.可以使用 context.getApplicationContext()

6.非静态内部类创建静态实例造成内存泄漏

       在 activity 内部创建一个非静态内部类的单例,每次启动 Activity 时都会使用该单例的数据,这样虽然   避免了资源的重复创建,但是会造成内存泄漏,因为非静态内部类默认会持有外部类的引用.可以将内部类设  置为静态内部类或者抽取出来封装成一个单例

7.匿名内部类如果被异步线程持有,此时如果没有任何措施则会造成内存泄漏

8.Handler 造成内存泄漏

       我们知道 Handler、Message 和 MessageQueue 都是相互关联在一起的,万一 Handler 发送的 Message 尚未被处理,则该 Message 及发送它的 Handler 对象将被线程 MessageQueue 一直持有。因 Handler 为非静态内部类,它会持有外部类的引用,因此可以将 Handler 声明为静态的

9.线程造成的内存泄漏

    例如:AsyncTask和Runnable

    AsyncTask和Runnable都使用了匿名内部类,那么它们将持有其所在Activity的隐式引用。如果任务在Activity销毁之前还未完成,那么将导致Activity的内存资源无法被回收,从而造成内存泄漏。

    解决方法:将AsyncTask和Runnable类独立出来或者使用静态内部类,这样便可以避免内存泄漏。

10.WebView造成的内存泄漏

    当我们不要使用WebView对象时,应该调用它的destory()函数来销毁它,并释放其占用的内存,否则其长期占用的内存也不能被回收,从而造成内存泄露。

    解决方法:

    为WebView另外开启一个进程,通过AIDL与主线程进行通信,WebView所在的进程可以根据业务的需要选择合适的时机进行销毁,从而达到内存的完整释放。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐