当前位置: 首页 > 后端技术 > Java

老徐和阿珍的故事:强引、软引、弱引、虚引,傻傻分不清楚

时间:2023-04-02 01:14:44 Java

人物背景:老徐,男,本名徐富贵,从事Javarelated从事研发多年,职场老手,钓鱼小能手。他虽然年纪不大,但长大了却更着急了。他叫老徐。据说他之前因为炒某币而输光了所有家产,现在还负债累累。阿珍,女,本名陈家珍,是一名刚入职的实习生。虽然是职场新人,但她聪明好学。据说她是校内四大美女之一,追求者从旺角排到铜锣湾,但至今仍单身。阿珍:“老徐,你这茶杯里泡的是什么?红的。”老徐:“这是枸杞。”阿珍:“枸杞子?你最近干什么去了,这么空虚!”老徐:“怎么可能?看我的身体,不弱!”阿珍笑道:“好软。””老徐红着脸辩解道:“我身体很好,很强,好吧。看到老徐狼狈的样子,阿震笑了。老徐起身准备离开的时候,阿真一把拉住老徐说:“跟你开个玩笑,我有一个严肃的问题,我分不清强引用、软引用、弱引用的区别。”,以及Java中的虚引用。告诉我让我们谈谈吧。”老徐立马自信的坐下,说道:“那你问对人了,我在这方面做了大量的研究。引文的四个级别从高到低依次为:强引文、软引文等。引用、弱引用、幻象引用。”强引用(StrongReference)强引用是Java中最常见的引用方式,99.99%都使用强引用。我们创建了一个对象并将其赋值给某个变量,我们就可以通过这个变量来操作实际的对象,例如:Stringname="WanmaoAcademy";System.out.println(name);当一个对象被强引用时通过一个或多个变量,它处于可达状态,不会被垃圾收集机制回收。即使在内存不足的情况下,Java虚拟机也宁愿抛出OutOfMemoryError异常也不愿回收这样的对象。软引用(SoftReference)软引用是通过SoftReference类实现的。当一个对象只有软引用时,Java虚拟机的垃圾回收机制运行后,内存空间充足时不会回收;当memory没有足够的空间时,它会被回收。例如:SoftReferencesoftReference=newSoftReference<>(newbyte[1024*1024*5]);System.out.println("垃圾回收前:"+softReference.get());//建议Java虚拟机进行垃圾回收System.gc();System.out.println("当内存足够时,之后垃圾回收:"+softReference.get());byte[][]bytes=newbyte[10][];for(inti=0;i<10;i++){bytes[i]=newbyte[1024*1024*1];}System.out.println("内存不足时,垃圾回收后:"+softReference。得到());在运行时添加-Xmx15M(设置Java堆最大内存为15M)和-XX:+PrintGC(启用垃圾回收日志打印)参数,可以看到如下结果:垃圾回收前:[B@1de0aca6[GC(System.gc())9173K->6495K(15872K),0.0033951secs][FullGC(System.gc())6495K->6434K(15872K),0.0149312secs]内存充足时,垃圾回收后:[B@1de0aca6[GC(分配失败)9588K->9570K(15872K),0.0013485秒][FullGC(人机工程学)9570K->9506K(15872K),0.0032467秒][FullGC(人机工程学)116254K-9>(15872K),0.0083257secs][FullGC(Ergonomics)13573K->13573K(15872K),0.0043525secs][FullGC(AllocationFailure)13573K->8435K(15872K),0.0065695secs]内存不足时,垃圾回收后:null可以看到,当内存空间足够时,软引用对象不会被回收;当内存空间不足时,通过WeakReference类实现软引用对象弱引用(WeakReference)。弱引用类似于软引用,但比软引用低一级。当一个对象只有弱引用时,Java虚拟机的垃圾回收机制运行后,不管内存是否充足都会被回收。例如:WeakReferenceweakReference=newWeakReference<>(newbyte[1024*1024*5]);System.out.println("垃圾回收前:"+weakReference.get());//建议Java虚拟机进行垃圾回收System.gc();System.out.println("内存充足时,垃圾回收后:"+weakReference.get());同样,在运行时添加-Xmx15M(设置最大Java堆内存为15M)和-XX:+PrintGC(开启垃圾回收的日志打印)参数,我们可以看到如下结果:垃圾回收前:[B@1de0aca6[GC(System.gc())9150K->6481K(15872K),0.0015689secs][FullGC(System.gc())6481K->1317K(15872K),0.0062846secs]内存足够时,垃圾回收后:null可见,即使内存足够,弱引用对象也会被回收。幻引用(PhantomReference)幻引用是通过PhantomReference类实现的,幻引用完全类似于无引用。如果一个对象只有一个幻象引用,则与没有引用一样好。幻影引用主要用于跟踪被垃圾收集的对象的状态。幻象引用不能单独使用,必须和一个引用队列(ReferenceQueue)一起使用。我们无法通过虚引用获取引用对象。只有对象被回收后,对象的虚引用才会被放入与虚引用关联的引用队列中,例如:ReferenceQueuereferenceQueue=newReferenceQueue();PhantomReferencephantomReference=newPhantomReference<>(newbyte[1024*1024*5],referenceQueue);System.out.println("垃圾回收前:"+phantomReference.get());byte[][]bytes=newbyte[10][];for(inti=0;i<5;i++){bytes[i]=newbyte[1024*1024*1];}System.out.println("垃圾回收后:"+referenceQueue.poll());同样,在运行时添加-Xmx15M(设置Java堆最大内存为15M)和-XX:+PrintGC(启用垃圾回收日志打印)参数,我们可以看到如下结果:beforegarbagecollection:null[GC(分配失败)9068K->6517K(15872K),0.0019272秒][GC(分配失败)9713K->9621K(15872K),0.0015966秒][FullGC(人机工程学)9621K->9506K(15872K),0.0092758秒]之后garbagecollection:java.lang.ref.PhantomReference@1de0aca6可以看到通过幻象引用是获取不到被引用对象的。对象被回收后,可以从引用队列中获取对应的幻象引用。老徐看着阿真一脸懵逼的样子,说道:“小朋友,你的问号很多吗?”“信息量有点大,我得慢慢消化。”阿珍回答道。老徐道:“没关系,我给你简单概括一下,很方便理解和记忆。”总结强引用:Java中最常用的引用方式,即使内存不足也不会被垃圾回收。软引用:当内存不足时,垃圾回收机制运行后回收对象。弱引用:无论内存是否充足,垃圾回收机制运行后对象都会被回收。幻象引用:主要用于跟踪被垃圾回收对象的状态,必须与引用队列一起使用。最后,谢谢你这么帅,给我点赞和关注。