Java 强应用、弱引用、软引用、虚引用
今天无意中看到了这四个名词,然后在脑海里过了一下,发现已经忘得一干二净了,因此写篇文章记录一下,俗话说好记性不如烂笔头。
那么先来解释下这4个名词吧
强引用(StrongReference):
强引用就是我们平常new的一个对象
Object a = new Object();
当内存空间不足的时候,java虚拟机宁愿抛出OOM异常,使程序异常终止,也不会靠随意回收有强引用的 对象来解决内存不足的问题,如果这个对象用完不用的时候可以通过 a = null;的这种方式来淡化引用;作用是帮助 垃圾收集器回收此对象;通过这种显示的方式设置a为null,gc会认为该对象不存在引用,这个时候gc就可以回收这个对象。
软引用(SoftReference):
如果一个对象只有软引用,并且内存足够的时候, 垃圾回收期就不会回收它;如果内存不足了,就会被回收这些对象的内存;主要垃圾回收期没有回收,该对象就可以一直被被程序使用。软引用可以被用来实现内存敏感的高速缓存。
public class SoftReferenceTest {
static class HeadObject{
byte[] bs = new byte[1024 * 1024];
}
public static void main(String[] args) {
SoftReference<HeadObject> softReference = new SoftReference<HeadObject>(new HeadObject());
List<HeadObject> list = new ArrayList<>();
while(true){
if(softReference.get()!= null){
list.add(new HeadObject());
System.out.println("list-add");
}else{
System.out.println("----软引用被回收");
break;
}
System.gc();
}
}
}
这段程序代码最后的结果是n多个list-add,最后是—软引用被回收
弱引用(WeakReference):
弱引用与软引用的区别在于:只具有弱引用的对象的生命周期更短。在垃圾收集器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管内存足够还是不足,都会进行回收。由于 垃圾回收期的线程比较低,一次不一定会很快发现那些具有弱引用的对象
public static void main(String[] args) throws InterruptedException {
WeakReference<TestObj> weakReference = new WeakReference(new TestObj());
System.out.println(weakReference.get() == null);
System.gc();
Thread.sleep(1000);
System.out.println(weakReference.get() == null);
}
让代码睡眠了1秒,gc之前的结果为true,gc之后的结果为false
虚引用(WeakReference):
虚引用:顾名思义,比较虚,就是形同虚设,又称为幻影引用,与其他几种都不同,虚引用不会决定对象的生命周期。如果一个对象仅是虚引用,那么他就和没有任何引用一样,在任何时候都可能被回收。
虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中。
总结:
四中引用的级别由高到低为:
强引用 > 软引用 > 弱引用 > 虚引用
在网上看到了比较通俗易懂的话来描述这四个引用:
- 强引用:就像是老板(OOM)的亲儿子一样,在公司可以什么事都不干,但是千万不要老是占用公司的资源为他自己做事,记得用完公司的妹子之后,要让她们去工作(资源要懂得释放) 不然公司很可能会垮掉的。
- 软引用:有点像老板(OOM)的亲戚,在公司表现不好有可能会被开除,即使你投诉他(调用GC)上班看片,但是只要不被老板看到(被JVM检测到)就不会被开除(被虚拟机回收)。
- 弱引用:就是一个普通的员工,平常如果表现不佳会被开除(对象没有其他引用的情况下),遇到别人投诉(调用GC)上班看片,那开除是肯定了(被虚拟机回收)。
- 虚引用:这货估计就是个实习生跟临时工把,遇到事情的时候想到了你,没有事情的时候,秒秒钟拿出去顶锅,开除。