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找到刚刚转换的文件

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

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