(5) Java的四种引用,强弱软虚,用到的场景。
《Thinking in Java》第四版中第518页讲解了这部分内容。引用如下:
java.lang.ref包含了一组类,这些类为垃圾回收提供了更大的灵活性,当存在可能会耗尽内存的大对象时,这些类就会显得特别有用。
在java.lang.ref包里面,有三个类SoftReference, WeakReference, PhantomReference继承自Reference类,他们从强到弱排列,代表着不同级别的“可获得性”。SoftReference可以用以实现内存敏感的告诉缓存;WeakReference是为实现“规范映射”而设计的,并不妨碍垃圾回收;PhantomReference用以调度回收前的清理工作,它比Java终止机制更灵活。
以下是摘自《Thinking in Java》的测试代码
package test;
import java.lang.ref.*;
import java.util.*;
class VeryBig{
private static final int SIZE = 10000;
private long[] la = new long[SIZE];
private String ident;
public VeryBig(String id){
ident = id;
}
public String toString(){
return ident;
}
protected void finalize(){
System.out.println("finalizing: " + ident);
}
}
public class References {
private static ReferenceQueue<VeryBig> rq = new ReferenceQueue<VeryBig>();
public static void checkQueue(){
Reference<? extends VeryBig> inq= rq.poll();
if(inq != null){
System.out.println("In quene: " + inq.get());
}
}
public static void main(String args[]){
int size = 2;
if(args.length > 0){
size = new Integer(args[0]);
}
LinkedList<SoftReference<VeryBig>> sa = new LinkedList<SoftReference<VeryBig>>();
for(int i = 0; i < size; i++){
sa.add(new SoftReference<VeryBig>(new VeryBig("soft" + i),rq));
System.out.println("Just Created: " + sa.getLast());
checkQueue();
}
LinkedList<WeakReference<VeryBig>> wa = new LinkedList<WeakReference<VeryBig>>();
for(int i = 0; i < size; i++){
wa.add(new WeakReference<VeryBig>(new VeryBig("weak" + i),rq));
System.out.println("Just Created: " + wa.getLast());
checkQueue();
}
SoftReference<VeryBig> s = new SoftReference<VeryBig>(new VeryBig("soft"));
WeakReference<VeryBig> w = new WeakReference<VeryBig>(new VeryBig("weak"));
System.gc();
LinkedList<PhantomReference<VeryBig>> qa = new LinkedList<PhantomReference<VeryBig>>();
for(int i = 0; i < size; i++){
qa.add(new PhantomReference<VeryBig>(new VeryBig("Phantom" + i),rq));
System.out.println("Just Created: " + qa.getLast());
checkQueue();
}
}
}
运行结果为:
Just Created: java.lang.ref.SoftReference@7852e922
Just Created: java.lang.ref.SoftReference@4e25154f
Just Created: java.lang.ref.WeakReference@70dea4e
Just Created: java.lang.ref.WeakReference@5c647e05
finalizing: weak
finalizing: weak1
finalizing: weak0
Just Created: java.lang.ref.PhantomReference@33909752
In quene: null
Just Created: java.lang.ref.PhantomReference@55f96302
In quene: null
由此可见softReference没有被回收,但是weakReference被回收掉了。
为了搞明白这几个reference,我查找了很多资料。现就WeakReference来进行深入讲解:
先看个例子:
package reference;
import java.lang.ref.WeakReference;
public class TestWeakReference {
public static void main(String[] args) {
Car car = new Car(22000,"silver");
WeakReference<Car> weakCar = new WeakReference<Car>(car);
int i=0;
while(true){
//System.out.print(car);
if(weakCar.get()!=null){
i++;
System.out.println("Object is alive for "+i+" loops - "+weakCar);
}else{
System.out.println("Object has been collected.");
break;
}
}
}
}
最后的运行结果为
“Object has been collected.”
也就是说对象最后还是被回收了。这是因为对于new出来的Car(22000,”silver”),GC线程发现已经跑到while循环中,指向它的强引用car没有被用到,只有一个弱引用weakCar还在。所以这个Car对象就被回收掉了。
所以在while循环中加下面这么一段话:
System.out.print(car);
Car对象就不会被回收掉了。
而SoftReference除了在GC回收前判断内存空间,其他的都与WeakReference一样。
因为有这个特性, soft reference比weak reference更加适合做cache objects的reference. 因为它可以尽可能的retain cached objects, 减少重建他们所需的时间和消耗.
以上内容来自不只是给面试加分 – Java WeakReference的理解与使用
为了理解GC在weakReference指向对象被回收时到底干了什么,我又查到了以下资料:
弱引用在GC的过程中,会被特殊处理。在GC的过程中,以copy gc为例,所有存活的强引用都会被拷到新的survivor区域中,但是弱引用不会被拷贝。同时会把WeakReference都使用它的discovered域串起来,在串的同时,把它的referent设置为 null,如下图所示。
WeakReference wr = new WeakReference(o);
第一种情况,当o已经是垃圾,也就是说,除了这个weak ref之外,再没有其他指向这个 o 的引用了。这种情况下,o就会被回收,并且wr的referent就会变成null,进而wr.get()就会是null。第二种情况,当o不是垃圾,那么毫无疑问,o会被拷贝到survivor空间,这时JVM就不会再把wr放到discovered链表中去了,并且还会把o的新地址更新到wr的referent(更新地址是什么意义,请具体参考前边的Copy GC的文章),这时,弱引用仍然存在。
而PhantomReference的作用是:
PhantomReference 唯一的用处就是跟踪 referent何时被 enqueue 到 ReferenceQueue 中.
具体就不再继续深入了。到了后面会再讲解WeakHashMap的内容。
(6)Hashcode的作用。
ArrayList、LinkedList、Vector的区别。
String、StringBuffer与StringBuilder的区别。
Map、Set、List、Queue、Stack的特点与用法。
HashMap和HashTable的区别。