面试官考察Java引用会问到强引用、弱引用、软引用、虚引用,具体有什么区别?本篇单独来详解mikechenJava引用 从JDK1。2版本开始,对象的引用被划分为4种级别,从而使程序能更加灵活地控制对象的生命周期,这4种级别由高到低依次为:强引用、软引用、弱引用和虚引用。 强引用 强引用是最普遍的引用,一般把一个对象赋给一个引用变量,这个引用变量就是强引用。 比如:preclassprettyprinthljsfsharpstylepadding:0。5fontfamily:Menlo,Monaco,Consolas,CourierNew,color:rgb(68,68,68);borderradius:4display:margin:0px0px1。5fontsize:14lineheight:1。5wordbreak:overflowwrap:whitespace:backgroundcolor:rgb(246,246,246);border:overflowx:fontstyle:fontvariantligatures:fontvariantcaps:fontweight:400;letterspacing:orphans:2;textalign:textindent:0texttransform:widows:2;wordspacing:0webkittextstrokewidth:0textdecorationthickness:textdecorationstyle:textdecorationcolor:强引用MikeChenmikechennewMikeChen();复制代码pre 在一个方法的内部有一个强引用,这个引用保存在Java栈中,而真正的引用内容(MikeChen)保存在Java堆中。 如果一个对象具有强引用,垃圾回收器不会回收该对象,当内存空间不足时,JVM宁愿抛出OutOfMemoryError异常。 如果强引用对象不使用时,需要弱化从而使GC能够回收,如下:preclassprettyprinthljsfsharpstylepadding:0。5fontfamily:Menlo,Monaco,Consolas,CourierNew,color:rgb(68,68,68);borderradius:4display:margin:0px0px1。5fontsize:14lineheight:1。5wordbreak:overflowwrap:whitespace:backgroundcolor:rgb(246,246,246);border:overflowx:fontstyle:fontvariantligatures:fontvariantcaps:fontweight:400;letterspacing:orphans:2;textalign:textindent:0texttransform:widows:2;wordspacing:0webkittextstrokewidth:0textdecorationthickness:textdecorationstyle:textdecorationcolor:帮助垃圾收集器回收此对象复制代码pre 显式地设置mikechen对象为null,或让其超出对象的生命周期范围,则GC认为该对象不存在引用,这时就可以回收这个对象,具体什么时候收集这要取决于GC算法。 举例:preclassprettyprinthljsdartstylepadding:0。5fontfamily:Menlo,Monaco,Consolas,CourierNew,color:rgb(68,68,68);borderradius:4display:margin:0px0px1。5fontsize:14lineheight:1。5wordbreak:overflowwrap:whitespace:backgroundcolor:rgb(246,246,246);border:overflowx:fontstyle:fontvariantligatures:fontvariantcaps:fontweight:400;letterspacing:orphans:2;textalign:textindent:0texttransform:widows:2;wordspacing:0webkittextstrokewidth:0textdecorationthickness:textdecorationstyle:textdecorationcolor:packagecom。mikechen。java。强引用举例authormikechenpublicclassStrongRefenenceDemo{publicstaticvoidmain(String〔〕args){Objecto1newObject();Objecto2o1;o1System。gc();System。out。println(o1);nullSystem。out。println(o2);java。lang。Object2503dbd3}}复制代码pre StrongRefenenceDemo中尽管o1已经被回收,但是o2强引用o1,一直存在,所以不会被GC回收。软引用 软引用是一种相对强引用弱化了一些的引用,需要用java。lang。ref。SoftReference类来实现。 比如:preclassprettyprinthljsruststylepadding:0。5fontfamily:Menlo,Monaco,Consolas,CourierNew,color:rgb(68,68,68);borderradius:4display:margin:0px0px1。5fontsize:14lineheight:1。5wordbreak:overflowwrap:whitespace:backgroundcolor:rgb(246,246,246);border:overflowx:fontstyle:fontvariantligatures:fontvariantcaps:fontweight:400;letterspacing:orphans:2;textalign:textindent:0texttransform:widows:2;wordspacing:0webkittextstrokewidth:0textdecorationthickness:textdecorationstyle:textdecorationcolor:StringstrnewString(abc);强引用SoftReferenceStringsoftRefnewSoftReferenceString(str);软引用复制代码pre 如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它,如果内存空间不足了,就会回收这些对象的内存。 先通过一个例子来了解一下软引用:preclassprettyprinthljsdartstylepadding:0。5fontfamily:Menlo,Monaco,Consolas,CourierNew,color:rgb(68,68,68);borderradius:4display:margin:0px0px1。5fontsize:14lineheight:1。5wordbreak:overflowwrap:whitespace:backgroundcolor:rgb(246,246,246);border:overflowx:fontstyle:fontvariantligatures:fontvariantcaps:fontweight:400;letterspacing:orphans:2;textalign:textindent:0texttransform:widows:2;wordspacing:0webkittextstrokewidth:0textdecorationthickness:textdecorationstyle:textdecorationcolor:弱引用举例authormikechenObjectobjnewObject();SoftReferencesoftRefnewSoftReferenceObject(obj);删除强引用调用gc对象依然存在System。gc();System。out。println(gc之后的值:softRef。get());复制代码pre 软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用对象被垃圾回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。preclassprettyprinthljscsstylepadding:0。5fontfamily:Menlo,Monaco,Consolas,CourierNew,color:rgb(68,68,68);borderradius:4display:margin:0px0px1。5fontsize:14lineheight:1。5wordbreak:overflowwrap:whitespace:backgroundcolor:rgb(246,246,246);border:overflowx:fontstyle:fontvariantligatures:fontvariantcaps:fontweight:400;letterspacing:orphans:2;textalign:textindent:0texttransform:widows:2;wordspacing:0webkittextstrokewidth:0textdecorationthickness:textdecorationstyle:textdecorationcolor:ReferenceQueueObjectqueuenewReferenceQueue();ObjectobjnewObject();SoftReferencesoftRefnewSoftReferenceObject(obj,queue);删除强引用调用gcSystem。gc();System。out。println(gc之后的值:softRef。get());对象依然存在申请较大内存使内存空间使用率达到阈值,强迫gcbyte〔〕bytesnewbyte〔10010241024〕;如果obj被回收,则软引用会进入引用队列R?referencequeue。remove();if(reference!null){System。out。println(对象已被回收:reference。get());对象为null}复制代码pre 软引用通常用在对内存敏感的程序中,比如高速缓存就有用到软引用,内存够用的时候就保留,不够用就回收。 我们看下Mybatis缓存类SoftCache用到的软引用:preclassprettyprinthljskotlinstylepadding:0。5fontfamily:Menlo,Monaco,Consolas,CourierNew,color:rgb(68,68,68);borderradius:4display:margin:0px0px1。5fontsize:14lineheight:1。5wordbreak:overflowwrap:whitespace:backgroundcolor:rgb(246,246,246);border:overflowx:fontstyle:fontvariantligatures:fontvariantcaps:fontweight:400;letterspacing:orphans:2;textalign:textindent:0texttransform:widows:2;wordspacing:0webkittextstrokewidth:0textdecorationthickness:textdecorationstyle:textdecorationcolor:publicObjectgetObject(Objectkey){OSoftReferenceObjectsoftReference(SoftReference)this。delegate。getObject(key);if(softReference!null){resultsoftReference。get();if(resultnull){this。delegate。removeObject(key);}else{synchronized(this。hardLinksToAvoidGarbageCollection){this。hardLinksToAvoidGarbageCollection。addFirst(result);if(this。hardLinksToAvoidGarbageCollection。size()this。numberOfHardLinks){this。hardLinksToAvoidGarbageCollection。removeLast();}}}}}复制代码pre 注意:软引用对象是在jvm内存不够的时候才会被回收,我们调用System。gc()方法只是起通知作用,JVM什么时候扫描回收对象是JVM自己的状态决定的,就算扫描到软引用对象也不一定会回收它,只有内存不够的时候才会回收。弱引用 弱引用的使用和软引用类似,只是关键字变成了WeakReference:preclassprettyprinthljsfsharpstylepadding:0。5fontfamily:Menlo,Monaco,Consolas,CourierNew,color:rgb(68,68,68);borderradius:4display:margin:0px0px1。5fontsize:14lineheight:1。5wordbreak:overflowwrap:whitespace:backgroundcolor:rgb(246,246,246);border:overflowx:fontstyle:fontvariantligatures:fontvariantcaps:fontweight:400;letterspacing:orphans:2;textalign:textindent:0texttransform:widows:2;wordspacing:0webkittextstrokewidth:0textdecorationthickness:textdecorationstyle:textdecorationcolor:MikeChenmikechennewMikeChen();WeakReferenceMikeChenwrnewWeakReferenceMikeChen(mikechen);复制代码pre 弱引用的特点是不管内存是否足够,只要发生GC,都会被回收。 举例说明:preclassprettyprinthljsdartstylepadding:0。5fontfamily:Menlo,Monaco,Consolas,CourierNew,color:rgb(68,68,68);borderradius:4display:margin:0px0px1。5fontsize:14lineheight:1。5wordbreak:overflowwrap:whitespace:backgroundcolor:rgb(246,246,246);border:overflowx:fontstyle:fontvariantligatures:fontvariantcaps:fontweight:400;letterspacing:orphans:2;textalign:textindent:0texttransform:widows:2;wordspacing:0webkittextstrokewidth:0textdecorationthickness:textdecorationstyle:textdecorationcolor:packagecom。mikechen。java。importjava。lang。ref。WeakR弱引用authormikechenpublicclassWeakReferenceDemo{publicstaticvoidmain(String〔〕args){Objecto1newObject();WeakReferenceObjectw1newWeakReferenceObject(o1);System。out。println(o1);System。out。println(w1。get());o1System。gc();System。out。println(o1);System。out。println(w1。get());}}复制代码pre弱引用的应用WeakHashMappreclassprettyprinthljstypescriptstylepadding:0。5fontfamily:Menlo,Monaco,Consolas,CourierNew,color:rgb(68,68,68);borderradius:4display:margin:0px0px1。5fontsize:14lineheight:1。5wordbreak:overflowwrap:whitespace:backgroundcolor:rgb(246,246,246);border:overflowx:fontstyle:fontvariantligatures:fontvariantcaps:fontweight:400;letterspacing:orphans:2;textalign:textindent:0texttransform:widows:2;wordspacing:0webkittextstrokewidth:0textdecorationthickness:textdecorationstyle:textdecorationcolor:publicclassWeakHashMapDemo{publicstaticvoidmain(String〔〕args)throwsInterruptedException{myHashMap();myWeakHashMap();}publicstaticvoidmyHashMap(){HashMapString,StringmapnewHashMapString,String();StringkeynewString(k1);Stringvaluev1;map。put(key,value);System。out。println(map);System。gc();System。out。println(map);}publicstaticvoidmyWeakHashMap()throwsInterruptedException{WeakHashMapString,StringmapnewWeakHashMapString,String();S刚开始写成了上边的代码思考一下,写成上边那样会怎么样?那可不是引用了StringkeynewString(weak);Smap。put(key,value);System。out。println(map);去掉强引用System。gc();Thread。sleep(1000);System。out。println(map);}}复制代码pre 当key只有弱引用时,GC发现后会自动清理键和值,作为简单的缓存表解决方案。ThreadLocalpreclassprettyprinthljsscalastylepadding:0。5fontfamily:Menlo,Monaco,Consolas,CourierNew,color:rgb(68,68,68);borderradius:4display:margin:0px0px1。5fontsize:14lineheight:1。5wordbreak:overflowwrap:whitespace:backgroundcolor:rgb(246,246,246);border:overflowx:fontstyle:fontvariantligatures:fontvariantcaps:fontweight:400;letterspacing:orphans:2;textalign:textindent:0texttransform:widows:2;wordspacing:0webkittextstrokewidth:0textdecorationthickness:textdecorationstyle:textdecorationcolor:staticclassThreadLocalMap{staticclassEntryextendsWeakReferenceThreadL?{OEntry(ThreadL?k,Objectv){super(k);}}。。。。。。}复制代码pre ThreadLocal。ThreadLocalMap。Entry继承了弱引用,key为当前线程实例,和WeakHashMap基本相同。虚引用 虚引用顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。 虚引用也称为幽灵引用或者幻影引用,它是最弱的一种引用关系。 虚引用需要java。lang。ref。PhantomReference来实现:preclassprettyprinthljsxmlstylepadding:0。5fontfamily:Menlo,Monaco,Consolas,CourierNew,color:rgb(68,68,68);borderradius:4display:margin:0px0px1。5fontsize:14lineheight:1。5wordbreak:overflowwrap:whitespace:backgroundcolor:rgb(246,246,246);border:overflowx:fontstyle:fontvariantligatures:fontvariantcaps:fontweight:400;letterspacing:orphans:2;textalign:textindent:0texttransform:widows:2;wordspacing:0webkittextstrokewidth:0textdecorationthickness:textdecorationstyle:textdecorationcolor:AanewA();ReferenceQueuerqnewReferenceQueue();PhantomReferenceprAnewPhantomReference(a,rq);复制代码pre 虚引用主要用来跟踪对象被垃圾回收器回收的活动。 虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列(ReferenceQueue)联合使用,当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。Java引用总结 java4种引用的级别由高到低依次为:强引用软引用弱引用虚引用。 来源:https:juejin。cnpost7131175540874018830