内存——Android中常见的内存泄漏

转载 2016年08月29日 13:40:07

1 、Activity对象未被回收

1 、Activity对象未被回收

本节是从《Eight Ways Your Android App Can Leak Memory》中学习并总结。

1.1 静态变量引用Activity对象

通过静态变量引用Activty对象时,会导致Activty对象所占内存内漏。主要是因为,静态变量是驻扎在JVM的方法区,因此,静态变量引用的对象是不会被GC回收的,因为它们所引用的对象本身就是GC ROOT(这块不清楚的请参考我的另一篇文章《JVM理解其实并不难! 》)。即最终导致Activity对象不被回收,从而也就造成内存泄漏。

看个简单例子,比如说,你应用启动Activty的场景很多,你希望定义一个工具类Util.Java,在这个类中,定义一个启动Activty的方法startActivity(Class nextActivity);以此来简化启动Activty的代码。另外,加入你当前的Activty启动另一个Activty的代码使用率也特别高。为了使得参数尽可能的少,你提供setFirstActivty,保存当前的Activty。代码如下:


在当前的Activty中,只需在onCreate中调用Util.setFirstActivity(this);,在需要启动另一个Activty处调用Util.startActivity(SecondActivity.class);。

在上面代码中,如果当前的Activty不再使用且Util中的sActivity对象没有更改,会导致当前Activty一直驻留在内存中。

1.2 静态View

有时,当一个Activity经常启动,但是对应的View读取非常耗时,我们可以通过静态View变量来保持对该Activity的rootView引用。这样就可以不用每次启动Activity都去读取并渲染View了。这确实是一个提高Activity启动速度的好方法!但是要注意,一旦View attach到我们的Window上,就会持有一个Context(即Activity)的引用。而我们的View有事一个静态变量,所以导致Activity不被回收。当然了,也不是说不能使用静态View,但是在使用静态View时,需要确保在资源回收时,将静态View detach掉。

1.3 内部类

我们知道,非静态内部类持有外部类的一个引用。因此,如果我们在一个外部类中定义一个静态变量,这个静态变量是引用内部类对象。将会导致内存泄漏!因为这相当于间接导致静态引用外部类。



1.4 匿名类

与内部类一样,匿名类也会持有外部类的引用。



1.5 Handler

我们知道,主线程的Looper对象不断从消息队列中取出消息,然后再交给Handler处理。如果在Activity中定义Handler对象,那么Handler肯定是持有Activty的引用。而每个Message对象是持有Handler的引用的(Message对象的target属性持有Handler引用),从而导致Message间接引用到了Activity。如果在Activty destroy之后,消息队列中还有Message对象,Activty是不会被回收的。当然了,如果消息正在准备(处于延时入队期间)放入到消息队列中也是一样的。


解决办法就是,将Handler放入单独的类或者将Handler放入到静态内部类中(静态内部类不会持有外部类的引用)。如果想要在handler内部去调用所在的外部类Activity,可以在handler内部使用弱引用的方式指向所在Activity,这样不会导致内存泄漏。

1.6 Threads和TimerTask

Threads和Timer导致内存泄漏的原因跟内部类一样。虽然在新的线程中创建匿名类,但是只要是匿名类/内部类,它都会持有外部类引用。


1.7 监听器

当我们需要使用系统服务时,比如执行某些后台任务、为硬件访问提供接口等等系统服务。我们需要把自己注册到服务的监听器中。然而,这会让服务持有 activity 的引用,如果程序员忘记在 activity 销毁时取消注册,那就会导致 activity 泄漏了。


2、集合对象造成的泄漏

当我们定义一个静态的集合类时,请注意,这可能会导致内存泄漏!前面我们提到过,静态变量所引用的对象是不会被回收掉的。而我的静态集合类中,包含有大量的对象,这些对象不会被回收。另外,如果集合中保存的对象又引用到了其他的大对象,如超长字符串、Bitmap、大数组等,很容易造成OOM。

3、资源对象没关闭造成内存泄漏

当我们打开资源时,一般都会使用缓存。比如读写文件资源、打开数据库资源、使用Bitmap资源等等。当我们不再使用时,应该关闭它们,使得缓存内存区域及时回收。虽然有些对象,如果我们不去关闭,它自己在finalize()函数中会自行关闭。但是这得等到GC回收时才关闭,这样会导致缓存驻留一段时间。如果我们频繁的打开资源,内存泄漏带来的影响就比较明显了。

4、使用对象池避免频繁创建对象

在我们需要频繁创建使用某个类时,或者是在for循环里面创建新的对象时,导致JVM不断创建同一个类。我们知道,在使用Message对象时,不是直接new出来的,而是通过obtain方法获取,以及recycle方法回收。这是典型的享元模式(不熟悉的同学参考《从Android代码中来记忆23种设计模式 》)。我们可以通过使用对象池来实现.



Android内存泄漏的常见场景及解决方案

哲学老师说,看待事物无非是了解它是什么,为什么,怎么做 所以,首先,我们先了解一下什么是“内存泄漏”   摘自百度的一段话:用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据...
  • Adrian24
  • Adrian24
  • 2016年11月20日 23:31
  • 771

Android中常见的内存泄漏汇总

Android中常见的内存泄漏汇总 集合类泄漏 集合类如果仅仅有添加元素的方法,而没有相应的删除机制,导致内存被占用。如果这个集合类是全局性的变量 (比如类中的静态属性,全局性的 ...
  • chen846262292
  • chen846262292
  • 2016年08月09日 16:12
  • 1049

Android开发——常见的内存泄漏以及解决方案(一)

0. 前言  Android的内存泄漏是Android开发领域永恒的话题,那今天就总结一下常见的内存泄漏吧。也给自己提个醒,在以后的编码过程中多注意这个问题。在Android Studio里可以通过一...
  • SEU_Calvin
  • SEU_Calvin
  • 2016年08月27日 12:37
  • 13994

Android之内存泄漏以及解决办法(持更)

Android之常见内存泄漏以及解决办法文章链接知识点: 单例造成的内存泄漏原因和解决方法; Handler造成的内存泄漏原因和解决方法; 耗时线程造成的内存泄漏原因和解决方法; 非静态内部类造成的内...
  • qq_16628781
  • qq_16628781
  • 2017年03月29日 00:27
  • 1650

Android中常出现的内存泄漏情况分析

Android中常出现的内存泄漏情况分析
  • Urchin_dong
  • Urchin_dong
  • 2016年02月12日 18:38
  • 863

Android内存优化-内存泄漏的几个场景以及解决方式

一.什么是内存泄漏 在Java程序中,如果一个对象没有利用价值了,正常情况下gc是会对其进行回收的,但是此时仍然有其他引用指向这个活在堆内存中的对象,那么gc就不会认为这个对象是一个垃圾,那么就不会...
  • JKerving
  • JKerving
  • 2016年08月20日 01:14
  • 1953

Android常见内存泄漏

Android常见内存泄漏标签(空格分隔): 性能优化性能优化是一个大的范畴,如果有人问你在Android中如何做性能优化的,也许都不知道从哪开始说起。首先要明白的是,为什么我们的App需要优化,最显...
  • baidu_17508977
  • baidu_17508977
  • 2016年11月24日 20:57
  • 441

Android中常见的内存泄漏

我们经常会在不经意间写出造成内存泄漏的代码,往往在代码上很难查出来。但是我们可以通过一些辅助工具来检测是否存在内存泄漏,比如通过AndroidStudio的monitors来查看内存的变化情况,或者是...
  • huachao1001
  • huachao1001
  • 2016年08月13日 15:42
  • 4988

Android Native进程内存泄露检测

Android Native进程内存泄露检测简介对于Android的native进程, Android源码中的Bionic库提供了一个很棒的API,get_malloc_leak_info用来检测Na...
  • u011280717
  • u011280717
  • 2016年07月04日 13:26
  • 2958

IE内存泄漏问题总结

IE内存泄漏模型 l  页面内脚本的动态刷新操作导致IE内存持续上升 l  页面内用F5或右键反复刷新,导致内存不断飙升 l  页面内变量占用的内存在退出该页面后,内存仍然无法回收 l  页面内变量占...
  • lichbin
  • lichbin
  • 2013年04月10日 18:29
  • 3350
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:内存——Android中常见的内存泄漏
举报原因:
原因补充:

(最多只允许输入30个字)