Android内存优化————虚引用与弱引用的使用及内存分析工具

一、虚引用

虚引用在实际的开发过程中应用的比较少。虚引用有一下几个特点:
(1)虚引用在垃圾回收器回收的时候被回收
(2)虚引用在通过get()方法获取的对象都为空,所以也被称为幽灵引用

(3)虚引用不会决定一个对象的生命周期,如果一个对象持有一个虚引用,那么它就和没有任何引用是一样的。

所以,根据上述的三个特点可以知道,虚引用主要用来监听所关联的对象什么时候被回收。操作如下:

    @Test
    public void testPhantomReference() throws InterruptedException {
        //队列,当对象被垃圾回收器回收的时候会被放到这个队列里
        ReferenceQueue<Object> referenceQueuee=new ReferenceQueue<>();
        //被关联的对象
        Object phantomObject=new Object();
        //创建一个虚引用
        PhantomReference phantomReference=new         
        PhantomReference(phantomObject,referenceQueuee);
        //将对象置空,之后等待被垃圾回收器回收
        phantomObject=null;
        System.out.println("phantomObject:"+phantomObject);//null
        //此时垃圾回收器还没回收置空的对象,所以队列的返回值是null
        System.out.println("referenceQueuee:"+referenceQueuee.poll());
        //isEnqueued:true表示已经被回收,false表示还未被回收。此时返回值是false
        System.out.println("isEnQueued:"+phantomReference.isEnqueued());
        System.gc();
        Thread.sleep(2000);
        System.out.println("-----------------------------------------");
        //注意:isEnqueued一定要在队列poll之前执行
        System.out.println("isEnQueued:"+phantomReference.isEnqueued());
        System.out.println("referenceQueuee:"+referenceQueuee.poll());
    }

输出如下:
 

phantomObject:null
referenceQueuee:null
isEnQueued:false
-----------------------------------------
isEnQueued:true
referenceQueuee:java.lang.ref.PhantomReference@f2a0b8e

二、弱引用

弱引用和虚引用有一定的区别。

(1)虚引用需要和ReferenceQueue配合使用,而弱引用则不需要。

(2)虚引用通过get()获取的对象为空,而弱引用则获取的是对象

所以使用弱引用可以很好的避免内存泄漏的问题。如果你想随时使用某个生命周期短的对象,又不影响它的回收,建议使用弱引用

    @Test
    public void testWeakReference() throws InterruptedException {
        ReferenceQueue<Object> referenceQueuee=new ReferenceQueue<>();
        Object weakObject=new Object();
        //弱引用,可以关联队列,也可以不管理。构造器有两种
        WeakReference weakReference=new WeakReference(weakObject,referenceQueuee);
        System.out.println("WeakReference:"+weakReference.get());
        System.out.println("isEnqueued:"+weakReference.isEnqueued());
        System.out.println("referenceQueuee:"+referenceQueuee.poll());
        weakObject=null;
        System.gc();
        Thread.sleep(2000);
        System.out.println("--------------------------------------");
        System.out.println("WeakReference:"+weakReference.get());
        System.out.println("isEnqueued:"+weakReference.isEnqueued());
        System.out.println("referenceQueuee:"+referenceQueuee.poll());
    }

输出如下:

WeakReference:java.lang.Object@593634ad
isEnqueued:false
referenceQueuee:null
--------------------------------------
WeakReference:null
isEnqueued:true
referenceQueuee:java.lang.ref.WeakReference@20fa23c1

三、内存分析工具

Android Studio有很好的分析内存及CPU分析工具Profile

和应用关联之后,会有如下的图展示

我们主要分析内存,所以点击上图红色框的部分,会变成如下的表现形式

关于Profile的使用,可以百度,可以对应用做出各种情况的分析。这里我说的是另外一种工具,可以和Profile配合使用,叫做MemoryAnalyzer。百度搜索,自行下载~

如何配合使用呢。

1.导出Profile某个时间段的内存数据

点击红色框的按钮,会出现黑色框的内容。在黑色框内容中,右键点击Export,保存。

2.修改导入的数据文件格式

进入到SDK路径———>platform-tools目录中,找到hprof-conv.exe文件。然后进入到cmd模式,或者加入到环境变量中。

#src_1.hprof:表示刚刚保存的内存数据文件
#dist_1.hprof:表示转换的内存数据文件
hprof-conv -z src_1.hprof dist_1.hprof

3.使用MemoryAnalyzer打开文件

点击File-->Open Heap Dump找到刚刚转换的文件

打开后基本如下,我们可以在下图的红色框部分寻找自己需要的数据,可以自己点击尝试阅读,或者百度一下相关的教程吧。

本篇文章到此结束,之后还会有第二篇内存优化的文章。欢迎提问,欢迎纠错!

猜你喜欢

转载自blog.csdn.net/qq_32019367/article/details/89814545