1. 快速理解java的四种引用
1.1 强引用
- 强引用就是通常用到的引用,它是如此之强,以至于JVM宁可抛出OOM异常(内存溢出)也不愿回收它们。
Object obj = new Obeject();
1.2 弱引用
- 弱引用可以帮你拿到强引用已不可达,但未被垃圾回收标记的对象,弱引用并不影响这些对象的生命周期。
@Test
public void testWeakReference(){
Object obj = new Object();
WeakReference<Object> weakReference = new WeakReference<Object>(obj);
obj = null;
Assert.assertNotNull(weakReference.get());
System.gc();
Assert.assertNull(weakReference.get());
}
1.3 软引用
- 软引用和弱引用的区别在于,软引用可达的对象只有在JVM内存不足时才会被回收,简单地说,它可以一定程度上影响对象的生命周期。
- 软引用常常被用于缓存。
@Test
public void testSoftReference() {
Object obj = new Object();
SoftReference<Object> softReference = new SoftReference<Object>(obj);
obj = null;
Assert.assertNotNull(softReference.get());
System.gc();
Assert.assertNotNull(softReference.get());
}
1.4 虚引用
- 无法通过虚引用拿到对象,但虚引用只有在对象完全被移出内存时才会加入到引用队列。
- 虚引用允许你知道具体何时其引用的对象从内存中移除,而实际上这是Java中唯一的方式,通过虚引用来执行析构动作比重写finalize方法更加安全高效(一个重写了finalize方法的对象如果想要被回收掉,需要经历两个单独的垃圾收集周期,更糟的是,理论上,这个即将被回收的对象是可以在一个不符合规范的析构方法里面重新复活)
private static final class ObjectOverrideFinalize {
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("finalize method executed");
}
}
@Test
public void testPhantomReference() throws InterruptedException{
ObjectOverrideFinalize obj = new ObjectOverrideFinalize();
WeakReference<ObjectOverrideFinalize> weakReference = new WeakReference<ReferencesTest.ObjectOverrideFinalize>(obj);
ReferenceQueue<ObjectOverrideFinalize> q = new ReferenceQueue<>();
PhantomReference<ObjectOverrideFinalize> phantomReference = new PhantomReference<>(obj, q);
obj=null;
Assert.assertNotNull(weakReference.get());
System.gc();
Thread.sleep(500);
Assert.assertNull(weakReference.get());
Assert.assertFalse(phantomReference.isEnqueued());
Assert.assertNull(q.poll());
System.gc();
Thread.sleep(500);
Assert.assertNull(weakReference.get());
Assert.assertTrue(phantomReference.isEnqueued());
Assert.assertNotNull(q.poll());
}
2. Reference抽象类
- java的三种引用(弱引用,软引用,虚引用)都继承自该抽象类;
- 由于Reference和垃圾收集密切相关,因此并不建议用户自行扩展抽象类。
Modifier and Type | Method and Description |
---|
void clear() | Clears this reference object. |
boolean enqueue() | Adds this reference object to the queue with which it is registered, if any. |
T get() | Returns this reference object’s referent. |
boolean isEnqueued() | Tells whether or not this reference object has been enqueued, either by the program or by the garbage collector. |
参考资料