准备Java面试之——Java SE基础知识解答(二)

来源:互联网 发布:长川软件 编辑:程序博客网 时间:2024/06/04 01:23

(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的区别。