Java中强引用、软引用、弱引用、虚引用内容解析------夜空中最亮的星

来源:互联网 发布:淘宝一元拍是真的吗 编辑:程序博客网 时间:2024/04/30 09:22

很高兴能写下这篇博客,因为这是对我学习新知识的总结,更重要的是可以同大家一起分享知识,畅游在知识的海洋。
欢迎留言,我会定时查阅留言,及时答复并改正博客的不足,请多包容,谢谢!你们也要多注意身体健康!
再苦再累,我不会放弃,因为夜空中最亮的星是我的梦。
谈到强引用(StrongReference)、软引用(SoftReference),弱引用(WeakReference)、虚引用(PhantomReference),会涉及到垃圾回收器机制GC。
什么是GC(全称:GabageCollection)?
GC通常是运行在一个独立的、优先级比较低的线程中,实时监测并释放“无效”的内存。
什么是“无效"的内存单元?
一般GC采用引用计数法来判断一个内存单元(一个变量)是否是无效的内存。
引用计数法(引用计数法只是GC中一种常用的方法,还会用到年代方法等)是指一个变量或一块内存当前被引用的次数,如果引用次数为0,则表示这个变量或这块内存未被引用,因此GC“有可能”去释放它 ,为什么说有可能?首先GC运行在一个独立的、优先级比较低的线程中,其次GC回收的具体工作也是比较复杂的,比如说需要释放大量内存的时候,而CPU资源又相对紧张,GC可能会选择性的释放一些内存资源,具体回收方法取决于GC内部的算法。
一个占用内存较大的对象、或者一个存储图片的对象,他们有时无用、又占用大量内存资源而GC又没有办法去释放,从而造成严重后果。一般原则是:对占用大量内存的变量使用完后主动将其置为NULL,可能的话主动调用一次GC回收机制:System.gc(),特别是一些static型的引用风险很大。

  /***大概译文:调用System.gc()方法时,会指示虚拟机去运行垃圾回收器,但这仅是一个提示作用,不会保证虚拟机实际运行* Indicates to the VM that it would be a good time to run the* garbage collector. Note that this is a hint only. There is no guarantee* that the garbage collector will actually be run.     */    public static void gc() {        boolean shouldRunGC;        synchronized(lock) {            shouldRunGC = justRanFinalization;            if (shouldRunGC) {                justRanFinalization = false;            } else {                runGC = true;            }        }        if (shouldRunGC) {            Runtime.getRuntime().gc();        }    }

1.强引用 StrongReference

强引用是使用最普遍的引用,如果一个对象具有强引用,垃圾回收器不会回收它。只有当其他对象没有对这个对象强引用时,才可能被GC回收掉。否则当内存空间不足

,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会回收强引用的对象。
/** * 测试强引用 */public void testStrongReference(){System.out.println("\n***************强引用********************\n");String strongStr = new String("强引用"); //强引用,永远不会被gc回收,即使程序因OutOfMemory而崩溃strongStr = null; //取消强引用,内存不足时,有可能被gc回收,因为gc处在的线程中优先级比较低System.gc();}

2.软引用 SoftReference:


如果一个对象具有软引用,当内存空间足够,垃圾回收器就不会回收它,当内存空间不足了,就可能回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以


被程序使用,软引用可用来实现内存敏感的高速缓存。一般对于这种占用内存资源比较大的,又不是必要的变量,或者一些占用大量内存资源的一些缓存的变量,就需要考虑


用SoftReference。
/** * 测试软引用 */public void testSoftReference(){System.out.println("\n***************软引用********************\n");String softStr = new String("软引用");ReferenceQueue softQueue = new ReferenceQueue();//如果gc预回收软引用,在回收前将该引用对象加入到ReferenceQueue中 SoftReference<String> softRef = new SoftReference<String>(softStr,softQueue);softStr = null; //取消强引用System.out.println("软引用...gc回收前...str = "+softRef.get());System.gc();if(softRef.get() == null){System.out.println("软引用...利用SoftReference判断...内存不足...gc已回收软引用...str = "+softRef.get());}else{System.out.println("软引用...利用SoftReference判断...内存充足...gc未回收软引用...");}Reference softPollRef = (Reference)softQueue.poll();if(softPollRef != null){System.out.println("软引用...利用ReferenceQueue判断...内存不足...gc已回收软引用...str = "+softPollRef.get());}else{System.out.println("软引用...利用ReferenceQueue判断...内存充足...gc未回收软引用...");}/** * 内存充足结果: 软引用...gc回收前...str = 软引用软引用...利用SoftReference判断...内存充足...gc未回收软引用...软引用...利用ReferenceQueue判断...内存充足...gc未回收软引用... */}

3. 弱引用 WeakReference


弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。如果一个对象只具有弱引用,只要垃圾回收器在内存空间检测到了,不管当前内存空间足够


与否,都会回收对应的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。
/** * 测试弱引用 */public void testWeakReference(){System.out.println("\n***************弱引用********************\n");//String weakStr = null; //弱引用,空值不会被加入到ReferenceQueue中String weakStr = new String("弱引用"); //强引用创建新的string类型数据//只有该引用对象被gc回收后,才会添加到(但不是一定)ReferenceQueue中,但被gc回收后,有时queue.poll中又没有数据ReferenceQueue weakQueue = new ReferenceQueue();WeakReference<String> weakReference = new WeakReference<String>(weakStr,weakQueue);weakStr = null; //取消强引用,gc才会回收弱引用对象System.out.println("弱引用...利用WeakReference判断...gc回收前...weakStr = "+weakReference.get());System.gc();System.out.println("弱引用...利用WeakReference判断...gc回收后...weakStr = "+weakReference.get());/** *  * 原文:(地址:Java? Platform Standard Ed. 6----http://docs.oracle.com/javase/6/docs/api/) * Polls this queue to see if a reference object is available.  * If one is available without further delay then it is removed  * from the queue and returned. Otherwise this method immediately returns null. *  * 译文: * 轮询此队列,查看引用对象是否可获得的。 * 如果一个引用对象是可获得的,并且没有进一步的延迟, * 然后它会被从队列中移除和返回。 * 如果该引用对象发生延迟,这个方法立即返回null *  *结论: *通过译文可以看到,如果对列中可获得的引用没有进一步延迟,该引用对象会被立即返回, *如果有延迟发生,这个方法立即返回null。所以reference有时等于null,有时不为null, *所以也就会出现以下注释的两种结果(结果1,结果2) * *要出现以下语意的结果,前提必须调用System.gc(),且该引用对象已取消强引用 */Reference weakPollRef = (Reference)weakQueue.poll();if(weakPollRef != null){System.out.println("弱引用...利用ReferenceQueue判断...gc已回收弱引用...queue中的值 = "+weakPollRef.get());}else{System.out.println("弱引用...利用ReferenceQueue判断...gc已回收弱引用......获得对列中的引用对象发生延迟...");}/*  结果1:  弱引用...利用WeakReference判断...gc回收前...weakStr = 弱引用弱引用...利用WeakReference判断...gc回收后...weakStr = null弱引用...利用ReferenceQueue判断...gc已回收弱引用......获得对列中的引用对象发生延迟... 结果2:    弱引用...利用WeakReference判断...gc回收前...weakStr = 弱引用弱引用...利用WeakReference判断...gc回收后...weakStr = null弱引用...利用ReferenceQueue判断...gc已回收弱引用...queue中的值 = null */}

4.虚引用 PhantomReference


如果一个对象只具有虚引用,那么它就和没有任何引用一样,随时会被jvm当作垃圾进行回收,虚引用主要是用于跟踪一个对象何时被GC回收。

/** * 测试虚引用 */public void testPhantomReference(){System.out.println("\n***************虚引用********************\n");String phantomStr = new String("虚引用测试");ReferenceQueue phantomQueue = new ReferenceQueue(); PhantomReference<String> phantomReference = new PhantomReference<String>(phantomStr, phantomQueue);phantomStr = null; //取消强引用/** * 有关phantomReference.get()的说明: *  * 原文: * Returns {@code null}.  The referent of a phantom reference is not *  accessible. *   * 译文: * phantomReference.get()返回空值,虚引用的引用对象是不可获得的 *  * 结论: *与译文可知,phantomReference.get()方法始终返回空值 */System.out.println("虚引用....利用PhantomReference...gc回收前...phantomStr = "+phantomReference.get());System.gc();System.out.println("虚引用....利用PhantomReference...gc回收后...phantomStr = "+phantomReference.get());/** * 同软引用一样,会出现两种结果,请详细查看软引用说明 * 要出现以下语意的结果,前提必须调用System.gc(),且该引用对象已取消强引用 */Reference phantomPollRef = phantomQueue.poll();if(phantomPollRef != null){System.out.println("虚引用....利用ReferenceQueue...gc已回收...phantomStr = "+phantomPollRef.get());}else{System.out.println("虚引用....利用ReferenceQueue...gc已回收虚引用......获得对列中的引用对象发生延迟......");}/** * 结果1:虚引用....利用PhantomReference...gc回收前...phantomStr = null虚引用....利用PhantomReference...gc回收后...phantomStr = null虚引用....利用ReferenceQueue...gc已回收...phantomStr = null *结果2: 虚引用....利用PhantomReference...gc回收前...phantomStr = null虚引用....利用PhantomReference...gc回收后...phantomStr = null虚引用....利用ReferenceQueue...gc已回收虚引用......获得对列中的引用对象发生延迟...... */}

                                             
1 0
原创粉丝点击