③. 弱引用: 发现即回收
①. 弱引用也是用来描述那些非必需对象,被弱引用关联的对象只能生存到下一次垃圾收集发生为止。在系统GC时,只要发现弱引用,不管系统堆空间使用是否充足,都会回收掉只被弱引用关联的对象
②. 但是,由于垃圾回收器的线程通常优先级很低,因此,并不一 定能很快地发现持有弱引用的对象。在这种情况下,弱引用对象可以存在较长的时间。
③. 弱引用和软引用一样,在构造弱引用时,也可以指定一个引用队列,当弱引用对象被回收时,就会加入指定的引用队列,通过这个队列可以跟踪对象的回收情况。
④. 软引用、弱引用都非常适合来保存那些可有可无的缓存数据。如果这么做,当系统内存不足时,这些缓存数据会被回收,不会导致内存溢出。而当内存资源充足时,这些缓存数据又可以存在相当长的时间,从而起到加速系统的作用
⑤. 在JDK1.2版之后提后了java.lang.ref.WeakReference类来实现弱引用
Object obj = new object(); //声明强引用 WeakReference<0bject> sf = new WeakReference<0bject>(obj); obj = null; //销毁强引用
⑥. 面试题:你开发中使用过WeakHashMap吗?
通过查看WeakHashMap源码,可以看到其内部类Entry使用的就是弱引用
line 702 -> private static class Entry<K,V> extends WeakReference implements Map.Entry<K,V> {…}
public class WeakReferenceTest { public static class User { public User(int id, String name) { this.id = id; this.name = name; } public int id; public String name; @Override public String toString() { return "[id=" + id + ", name=" + name + "] "; } } public static void main(String[] args) { //构造了弱引用 WeakReference<User> userWeakRef = new WeakReference<User>(new User(1, "songhk")); //从弱引用中重新获取对象 System.out.println(userWeakRef.get()); System.gc(); // 不管当前内存空间足够与否,都会回收它的内存 System.out.println("After GC:"); //重新尝试从弱引用中获取对象 System.out.println(userWeakRef.get()); } }
④. 虚引用: 对象回收跟踪
①. 虚引用(Phantom Reference),也称为“幽灵引用”或者“幻影引用”,是所有引用类型中最弱的一个。
②. 为一个对象设置虚引用关联的唯一目的在于跟踪垃圾回收过程。比如:能在这个对象被收集器回收时收到一个系统通知。
③. 虚引用必须和引用队列一起使用。虚引用在创建时必须提供一个引用队列作为参数。当垃圾回收器准备回收一个对象时,如果发现它还有虛引用,就会在回收对象后,将这个虚引用加入引用队列,以通知应用程序对象的回收情况。虚引用的get方法总是返回给null,因此无法访问对应的引用对象 理解
④. 由于虚引用可以跟踪对象的回收时间,因此,也可以将一些资源释放操作放置在虛引用中执行和记录‘’
⑤. 在JDK 1. 2版之后提供了PhantomReference类来实现虚引用。
object obj = new object(); ReferenceQueuephantomQueue = new ReferenceQueue( ) ; PhantomReference<object> pf = new PhantomReference<object>(obj, phantomQueue); obj = null;
⑥. 测试代码
/*** * -xms10m -xmx10m */ public class MyObject { public static void main(String[] args) { ReferenceQueue<MyObject> referenceQueue = new ReferenceQueue(); PhantomReference<MyObject> phantomReference = new PhantomReference<>(new MyObject(),referenceQueue); //System.out.println(phantomReference.get()); List<byte[]> list = new ArrayList<>(); new Thread(() -> { while (true) { list.add(new byte[1 * 1024 * 1024]); try { TimeUnit.MILLISECONDS.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(phantomReference.get()); } },"t1").start(); new Thread(() -> { while (true) { Reference<? extends MyObject> reference = referenceQueue.poll(); if (reference != null) { //下面这句话被打印出说明进行了gc,然后将对象放在了引用队列中,我们可以使用poll方法获取 System.out.println("***********有虚对象加入队列了"+reference); } } },"t2").start(); //暂停几秒钟线程 try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } } @Override protected void finalize() throws Throwable { // gc finalize method over 这句话被打印出来,说明进行了gc System.out.println("gc finalize method over"); } }