一、虚引用
虚引用在实际的开发过程中应用的比较少。虚引用有一下几个特点:
(1)虚引用在垃圾回收器回收的时候被回收
(2)虚引用在通过get()方法获取的对象都为空,所以也被称为幽灵引用
(3)虚引用不会决定一个对象的生命周期,如果一个对象持有一个虚引用,那么它就和没有任何引用是一样的。
所以,根据上述的三个特点可以知道,虚引用主要用来监听所关联的对象什么时候被回收。操作如下:
public class PhantomTest {
ReferenceQueue<Object>referenceQueue = new ReferenceQueue<>();
Object obj = new Object();
PhantomReference phantomReference = new PhantomReference(obj,referenceQueue);
public void start(){
new Thread(()->{
System.out.println("reference.get()="+phantomReference.get());
PhantomReference<Object>reference = null;
try {
reference = (PhantomReference<Object>) referenceQueue.remove();
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println("虚引用回收:"+reference);
}).start();
}
public static void main(String[] args) throws InterruptedException {
PhantomTest test = new PhantomTest();
test.start();
test.obj = null;
Thread.sleep(5000);
System.gc();
Thread.sleep(5000);
}
}
输出如下:
reference.get()=null
虚引用回收:java.lang.ref.PhantomReference@2951cacb
(1)PhantomReference调用get方法获取的值是空
(2)在子线程中,调用referenceQueue.remove()方法来获取队列中的数据,如果队列中没有数据,则会阻塞;虚引用被回收时,虚引用的对象会加入到ReferenceQueue中,阻塞停止,继续向下执行。
二、弱引用
弱引用和虚引用有一定的区别。
(1)虚引用需要和ReferenceQueue配合使用,而弱引用则不需要。
(2)虚引用通过get()获取的对象为空,而弱引用则获取的是对象
所以使用弱引用可以很好的避免内存泄漏的问题。如果你想随时使用某个生命周期短的对象,又不影响它的回收,建议使用弱引用
public class WeakTest {
ReferenceQueue<Object>referenceQueue = new ReferenceQueue<>();
Object object = new Object();
WeakReference<Object>weakReference = new WeakReference<>(object,referenceQueue);
public void start(){
new Thread(()->{
System.out.println("reference.get()="+weakReference.get());
WeakReference<Object>reference = null;
try {
reference = (WeakReference<Object>) referenceQueue.remove();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("弱引用对象:"+reference);
System.out.println("reference.get()=:"+reference.get());
}).start();
}
public static void main(String[] args) throws InterruptedException {
WeakTest test = new WeakTest();
test.start();
test.object = null;
Thread.sleep(5000);
System.out.println("启动gc");
System.gc();
Thread.sleep(5000);
}
}
输出如下:
reference.get()=java.lang.Object@67f9d772
======================
弱引用对象:java.lang.ref.WeakReference@693e25fd
reference.get()=:null
从输出结果中,我们可以看到,在Object对象回收之前,reference.get方法返回了Object的引用地址;回收之后,reference.get方法返回的是null
三、软引用
软引用的用法和弱引用的用法基本一样,不过不能像上面的代码一样做测试,因为只有当堆空间不够时,软引用才会被回收,所以我们需要模拟堆空间不足的情况:第一、修改堆空间的大小;第二不断创建垃圾对象
如图,-Xms20m表示堆空间的初始大小,-Xmx20m表示堆空间的最大值。
public class SoftTest {
ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
Object object = new Object();
SoftReference<Object>softReference = new SoftReference<>(object,referenceQueue);
public void start(){
new Thread(()->{
System.out.println("reference.get()="+softReference.get());
SoftReference<Object> reference = null;
try {
reference = (SoftReference<Object>) referenceQueue.remove();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("软引用对象:"+reference);
System.out.println("reference.get()=:"+reference.get());
}).start();
}
/**
* 创建垃圾
*/
public static void createGarbage(){
List<byte[]> list = new LinkedList<>();
for (int i = 0; i <100; i++) {
list.add(new byte[1024*1024]);
}
}
public static void main(String[] args) throws InterruptedException {
SoftTest test = new SoftTest();
test.start();
test.object = null;
Thread.sleep(5000);
System.out.println("======================");
System.gc();
createGarbage();
Thread.sleep(5000);
}
}
createGarbage方法在不断创建垃圾对象,当内存不足时,就会对软引用进行回收了,输出如下:
reference.get()=java.lang.Object@706fe943
======================
软引用对象:java.lang.ref.SoftReference@7ea8093e
reference.get()=:null
当然这段代码会由于堆空间不足而崩溃
四、内存分析工具
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找到刚刚转换的文件
打开后基本如下,我们可以在下图的红色框部分寻找自己需要的数据,可以自己点击尝试阅读,或者百度一下相关的教程吧。
本篇文章到此结束,之后还会有第二篇内存优化的文章。欢迎提问,欢迎纠错!