一.概述
强引用:
如果一个对象具备强引用,则无论如何,垃圾回收器gc绝不会将其回收,宁愿最终抛出OutOfMemoryError错误,使程序异常终止,也不会随意回收具备强引用的对象。
软引用:
如果一个对象具备软引用则内存空间足够时,垃圾回收器不会将其回收,但是当内存不够时,就会回收这些对象的内存,只要垃圾回收没有回收它则其可以一直被程序所使用,软引用可以用来实现内存敏感的高速缓存。
弱引用:
只具有弱引用的对象的生命周期非常短,在垃圾回收线程扫描其所管辖的区域时一旦发现弱引用对象则无论当前内存是否足够,都会将其回收,但是需要注意的是垃圾回收线程的优先级一般来说具备非常低的线程优先级,因此不会很快发现那些只具备弱引用的对象。
虚引用:
顾名思义虚引用代表着虚无缥缈,并且其不会决定对象的生命周期,即当一个对象仅仅持有虚引用时,那么它就跟没有持有任何引用一样任何时候都会被回收。
二.具体作用
强引用:
强引用具备非常实用的功能,例如:在ArrayList的实现源代码中clear()方法
private transient Object[] elementData;
public void clear() {
modCount++;
// Let gc do its work
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}
当数组 elementData被赋值为null时垃圾回收器不会将其回收,这是因为它是一个强引用类型方便了其在接下来的add()添加元素等其他操作时,不用重新分配内存空间,同时又可以及时释放内存。
软引用:
软引用的实现通过SoftReference来实现 如下:
String str=new String(“abc”); // 强引用
SoftReference softRef=new SoftReference(str); // 软引用
当内存不足时,等价于:
If(JVM.内存不足()) {
str = null; // 转换为软引用
System.gc(); // 垃圾回收器进行回收
}
软引用也具备着非常实际的作用例如:在浏览网页时点击网页上的后退按钮是重新进行请求还是在缓存中取呢
(1)如果一个网页在浏览结束时就进行内容的回收,则按后退查看前面浏览过的页面时,需要重新构建
(2)如果将浏览过的网页存储到内存中会造成内存的大量浪费,甚至会造成内存溢出
这时候就可以使用软引用
Browser prev = new Browser(); // 获取页面进行浏览
SoftReference sr = new SoftReference(prev); // 浏览完毕后置为软引用
if(sr.get()!=null){
rev = (Browser) sr.get(); // 还没有被回收器回收,直接获取
}else{
prev = new Browser(); // 由于内存吃紧,所以对软引用的对象回收了
sr = new SoftReference(prev); // 重新构建
}
弱引用:
如果这个对象是偶尔的使用,并且希望在使用时随时就能获取到,但又不想影响此对象的垃圾收集,那么你应该用 Weak Reference (弱引用的实现类)来记住此对象。
String str=new String("abc");
WeakReference<String> abcWeakRef = new WeakReference<String>(str);
str=null;
在垃圾回收器进行扫描回收时等价于
str = null;
System.gc();
下面的代码会让str再次变为一个强引用:
String abc = abcWeakRef.get();
虚引用:
虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中。
三.总结
Java4种引用的级别由高到低依次为:
强引用 > 软引用 > 弱引用 > 虚引用
引用类型 被垃圾回收时间 用途 生存时间
强引用 | 从来不会| | 对象的一般状态 | | JVM停止运行时终止|
软引用 | 在内存不足时| |对象缓存 | | 内存不足时终止|
弱引用 | 在垃圾回收时| |对象缓存 | | gc运行后终止|
虚引用 | Unknown | | Unknown | | Unknown|