Android内存泄漏分析及实践(一)

来源:互联网 发布:怎样在淘宝上做供应商 编辑:程序博客网 时间:2024/06/07 17:33

Android内存泄漏分析及实践(一)

写本博客的目的是希望广大程序猿平时写android(java)代码的时候充分认识到内存问题不仅仅是C,C++才会出现的。虽然JVM帮助程序猿对内存进行管理,但是还是存在内存无法释放的情况,导致该释放的内存无法被系统回收。导致程序不断GC,造成程序卡顿,甚至出现ANR或者OOM。

我们通过以下几个方面来分析内存泄漏:

1 内存泄漏概念

2 内存泄露常见例子

3 引用分类

4 ReferenceQueue和JVM关系

5 对象在什么情况下才有可能被释放

6 GC在什么时候执行

7 如何判断对象是否被回收

一. 内存泄漏概念

指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段内存的控制,因而造成了内存的浪费。

二. 内存泄露常见例子

2.1 对象被静态变量持有

public class MemoryLeak {    private void transObj(){        new PersistentClass(this);    }}class PersistentClass {    static MemoryLeak obj;    public PersistentClass(MemoryLeak memoryLeak){        obj = memoryLeak;    }}

如果PersistentClass生命周期比MemoryLeak 长,就会出现内存泄漏。

2.2 监听器未反注册

getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {    @Override    public void onGlobalLayout() {        //do some thing,and not remove GlobalLayoutListener    }});

三. 引用分类

引用分为强引用(Reference),软引用(softReference),弱引用(WeakReference)和虚引用(PhantomReference)。

  • Reference: 最常见的引用方式,只有当对象不可达时,才有可能被回收。

  • SoftReference: 如果内存空间足够,垃圾回收器就不会回收它,如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。

  • WeakReference: 如果一个对象只具有弱引用,那就类似于可有可无的生活用品。 弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它 所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程, 因此不一定会很快发现那些只具有弱引用的对象。

  • PhantomReference: “虚引用“顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收。虚引用在创建的时候必须要传ReferenceQueue。

引用由强到弱关系为:
Reference > SoftReference > WeakReference >PhantomReference

String str = new String("hello"); //①强引用SoftReference<String> sf = new SoftReference<String>(str); //② 软引用ReferenceQueue<String> rq = new ReferenceQueue<String>();WeakReference<String> wf = new WeakReference<String>(str, rq); //③ 弱引用PhantomReference<String> wf = new PhantomReference<String>(str, rq); //④ 虚引用

四. ReferenceQueue和JVM关系

这里写图片描述

Reference依赖ReferenceQueue,JVM直接操作Reference,通过Reference操作ReferenceQueue。

五. 对象在什么情况下才有可能被释放

当对象是弱可到达,或者虚可到达的时候,对象才有可能被回收。
弱可到达(虚可到达):到对象不存在强引用和软引用的时候,只有弱引用(或者虚引用)。

六. GC在什么时候执行

gc执行是随机的。但我们可以通过下面的方法来增加JVM执行GC的概率(实验证明非常有效)。

// Code taken from AOSP FinalizationTest:// https://android.googlesource.com/platform/libcore/+/master/support/src/test/java/libcore/// java/lang/ref/FinalizationTester.java// System.gc() does not garbage collect every time. Runtime.gc() is// more likely to perfom a gc.Runtime.getRuntime().gc(); Thread.sleep(100);System.runFinalization();

七. 如何判断对象是否被回收

To make the Thread object weakly reachable, its strong reference must be set to null. After the garbage collector clears the weak reference to the thread, it places the weak reference on the queue

Object o = new Object();ReferenceQueue rq = new ReferenceQueue ();WeakReference wf = new WeakReference(o, rq);o = null;

当对象o被jvm回收的时候
1 jvm将WeakReference的referent赋值为null;
2 jvm然后将WeakReference实例赋值给pending;
3 jvm最后调用Reference.ReferenceHandler将pending放到ReferenceQueue中

结论:我们可以通过查询ReferenceQueue是否包含WeakReference实例,判断对象 o是否被系统回收

1 0
原创粉丝点击