您的位置:首页 > 移动开发 > Android开发

【Android内存泄漏】关于内存泄漏(三)

2016-06-09 23:31 453 查看
什么是内存泄漏

Android虚拟机的垃圾回收采用的是根搜索算法。GC(垃圾回收机制)会从根节点(GC Roots)开始对Heap进行遍历。到最后,部分没有直接或者间接引用到GC Roots的就是需要回收的垃圾,会被GC回收掉。而内存泄漏出现的原因就是存在了无效的引用,导致本来需要被GC回收的对象没有被回收。

在之前的博客有提到内存泄漏的部分内容,关于内存泄漏(二)

如下是常犯的错误:

public class MyClass{
private static MyClass instance;
private Context context;
private MyClass(Context context){
this.context=context;
}
public static MyClass getIntance(Context context){
if(instance==null){
synchronized(MyClass.class){
if(instance==null){
instance=new MyClass(context);
}
}
}
return instance;
}
}


假如在某个Activity中需要调用MyClass中的getInstance时,选择传入的参数是Activity的context时,则有可能发生内存泄漏的风险,当instance没有释放时,Activity会一直存在,因此造成内存泄漏。

关于Android内存泄漏,在知乎上有这么个提问:使用getApplicationContext()替代getContext()就可以避免内存泄漏吗?

关于这个问题,首先要注意一点:并不是所有的Context都可以用getApplicationContext()获取到。在Dialog中就需要Activity,不过getApplicationContext()确实在一定基础上可以减少内存泄漏。所以能用getApplicationContext的情况下尽量使用。

列举是否可使用的表格总结:



非静态内部类导致内存泄漏,例如Handler,这个时候我们应当将内部写为静态内部类,在静态内部类中使用软引用/弱引用持有外部类的实例。

(软引用和弱引用指什么呢?)

1.强引用(StrongReference):

强引用是使用最为普遍的引用,如果一个对象具有强引用,那么垃圾回收机制就绝不会回收它。如:Object ob=new Object();

Obj就是强引用。

当内存不足时,JVM即使是抛出OutofMemoryError错误,也不会轻易去回收掉强引用的对象,这个时候我们可能就需要弱化引用,让垃圾回收机制可以回收它,如: Obj=null.

2.软引用(SoftReference):

当内存足够的时候,垃圾回收机制是不会回收软引用的,但是当内存不够的时候,垃圾回收机制就会回收这些软引用,而软引用可以用来实现内存敏感度高的高速缓存。

如:

String s=new String(“Hello world”);

SoftReference str=new Softreference(s);

3.弱引用(weakReference):

弱引用对象只具有极其短暂的生命周期,在垃圾回收器扫描它所管辖的内存区域的过程中,一旦发现只具有弱引用的对象,那么不管内存是否足够,该弱引用对象都会被垃圾回收机制回收,值得注意的一点是垃圾回收线程是优先级很低的线程,所以不一定能立刻扫描到弱引用。

4.虚引用(PhantomRefrence):

虚引用不会决定对象的生命周期,虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中。

这些都是Java的特性,有必要去深入理解下,内存泄漏方面能优化的地方都是值得去优化的。

在Android开发上,必须铭记一点:内存有谁申请占用,就应该由谁来释放内存。保证这一点,可以避免很多内存不释放,最终导致内存泄漏的现象。

善用WeakReference

Exception里面要释放资源

界面不可见时,停止所有动画和相关线程

少用帧间动画,真要用的时候,用SurfaceView做

异步任务队列一定要用有界队列

读SqlLite的时候请尽量不要在UI线程,虽然你这样做也不会Exception

善用LeakCanary

再次复习下GC,看看Java对垃圾回收的思想和流程:

首先要了解到,垃圾回收机制不是万能的,有人问过我,Java有了垃圾回收机制,为什么还要自己去释放资源?

其实垃圾回收机制也有不能直接自动去回收的对象,当对象和外部资源有联系时就不能立即释放资源了,例如File等。

另外需要知道:GC的运行时间是不确定的,而这就意味着你无法直接控制回收垃圾的时机,在内存不足的时候你想通过垃圾回收来释放内存,但是GC却不能立即执行。同时GC运行的阶段也会占用系统资源,那么当你想推迟GC的时间,延缓占用也是很难控制的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  内存泄露 android