副标题#e#
StrongReference、SoftReference、WeakReference、PhantomReferenceJava引用总结–StrongReference、SoftReference、WeakReference、PhantomReference
1 Java引用先容
Java从1.2版本开始引入了4种引用,这4种引用的级别由高到低依次为:
强引用 > 软引用 > 弱引用 > 虚引用
⑴强引用(StrongReference)
强引用是利用最普遍的引用。假如一个工具具有强引用,那垃圾接纳器毫不会接纳它。当内存空间不敷,Java虚拟机甘愿抛出OutOfMemoryError错误,使措施异常终止,也不会靠随意接纳具有强引用的工具来办理内存不敷的问题。
⑵软引用(SoftReference)
假如一个工具只具有软引用,则内存空间足够,垃圾接纳器就不会接纳它;假如内存空间不敷了,就会接纳这些工具的内存。只要垃圾接纳器没有接纳它,该工具就可以被措施利用。软引用可用来实现内存敏感的高速缓存。
软引用可以和一个引用行列(ReferenceQueue)连系利用,假如软引用所引用的工具被垃圾接纳器接纳,Java虚拟机就会把这个软引用插手到与之关联的引用行列中。
⑶弱引用(WeakReference)
弱引用与软引用的区别在于:只具有弱引用的工具拥有更短暂的生命周期。在垃圾接纳器线程扫描它所统领的内存区域的进程中,一旦发明白只具有弱引用的工具,不管当前内存空间足够与否,城市接纳它的内存。不外,由于垃圾接纳器是一个优先级很低的线程,因此不必然会很快发明那些只具有弱引用的工具。
弱引用可以和一个引用行列(ReferenceQueue)连系利用,假如弱引用所引用的工具被垃圾接纳,Java虚拟机就会把这个弱引用插手到与之关联的引用行列中。
⑷虚引用(PhantomReference)
“虚引用”顾名思义,就是形同虚设,与其他几种引用都差异,虚引用并不会抉择工具的生命周期。假如一个工具仅持有虚引用,那么它就和没有任何引用一样,在任何时候都大概被垃圾接纳器接纳。
虚引用主要用来跟踪工具被垃圾接纳器接纳的勾当。虚引用与软引用和弱引用的一个区别在于:虚引用必需和引用行列 (ReferenceQueue)连系利用。当垃圾接纳器筹备接纳一个工具时,假如发明它尚有虚引用,就会在接纳工具的内存之前,把这个虚引用插手到与之 关联的引用行列中。
由于引用和内存接纳干系细密。下面,先通过实例对内存接纳有个认识;然后,进一步通过引用实例加深对引用的相识。
2 内存接纳
建设民众类MyDate,它的浸染是包围finalize()函数:在finalize()中输出打印信息,利便追踪。
说明:finalize()函数是在JVM接纳内存时执行的,但JVM并不担保在接纳内存时必然会挪用finalize()。
MyDate代码如下:
package com.skywang.java; import java.util.Date; public class MyDate extends Date { /** Creates a new instance of MyDate */ public MyDate() { } // 包围finalize()要领 protected void finalize() throws Throwable { super.finalize(); System.out.println("obj [Date: " + this.getTime() + "] is gc"); } public String toString() { return "Date: " + this.getTime(); } }
在这个类中,对java.util.Date类举办了扩展,并重写了finalize()和toString()要领。
建设民众类ReferenceTest,它的浸染是界说一个要领drainMemory():耗损大量内存,以此来激发JVM接纳内存。
ReferenceTest代码如下:
package com.skywang.java; public class ReferenceTest { /** Creates a new instance of ReferenceTest */ public ReferenceTest() { } // 耗损大量内存 public static void drainMemory() { String[] array = new String[1024 * 10]; for(int i = 0; i < 1024 * 10; i++) { for(int j = 'a'; j <= 'z'; j++) { array[i] += (char)j; } } } }
在这个类中界说了一个静态要领drainMemory(),此要领旨在耗损大量的内存,促使JVM运行垃圾接纳。
有了上面两个民众类之后,我们即可测试JVM什么时候举办垃圾接纳。下面分3种环境举办测试:
环境1:排除工具
实现代码:
package com.skywang.java; public class NoGarbageRetrieve { public static void main(String[] args) { MyDate date = new MyDate(); date = null; } }
运行功效:
<无任何输出>
功效阐明:date固然设为null,但由于JVM没有执行垃圾接纳操纵,MyDate的finalize()要领没有被运行。
环境2:显式挪用垃圾接纳
#p#分页标题#e#
实现代码:
package com.skywang.java; public class ExplicitGarbageRetrieve { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub MyDate date = new MyDate(); date = null; System.gc(); } }
运行功效:
obj [Date: 1372137067328] is gc
功效阐明:挪用了System.gc(),使JVM运行垃圾接纳,MyDate的finalize()要领被运行。
环境3:隐式挪用垃圾接纳
实现代码:
package com.skywang.java; public class ImplicitGarbageRetrieve { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub MyDate date = new MyDate(); date = null; ReferenceTest.drainMemory(); } }
运行功效:
obj [Date: 1372137171965] is gc
功效阐明:固然没有显式挪用垃圾接纳要领System.gc(),可是由于运行了淹灭大量内存的要领,触发JVM举办垃圾接纳。
总结:JVM的垃圾接纳机制,在内存富裕的环境下,除非你显式挪用System.gc(),不然它不会举办垃圾接纳;在内存不敷的环境下,垃圾接纳将自动运行
3、Java对引用的分类
3.1 强引用
实例代码:
package com.skywang.java; public class StrongReferenceTest { public static void main(String[] args) { MyDate date = new MyDate(); System.gc(); } }
运行功效:
#p#副标题#e#
<无任何输出>
功效说明:纵然显式挪用了垃圾接纳,可是用于date是强引用,date没有被接纳。
3.2 软引用
实例代码:
package com.skywang.java; import java.lang.ref.SoftReference; public class SoftReferenceTest { public static void main(String[] args) { SoftReference ref = new SoftReference(new MyDate()); ReferenceTest.drainMemory(); } }
运行功效:
<无任何输出>
功效说明:在内存不敷时,软引用被终止。软引用被克制时,
SoftReference ref = new SoftReference(new MyDate());
ReferenceTest.drainMemory();
等价于
MyDate date = new MyDate();
// 由JVM抉择运行
If(JVM.内存不敷()) {
date = null;
System.gc();
}
3.3 弱引用
示例代码:
package com.skywang.java; import java.lang.ref.WeakReference; public class WeakReferenceTest { public static void main(String[] args) { WeakReference ref = new WeakReference(new MyDate()); System.gc(); } }
运行功效:
obj [Date: 1372142034360] is gc
功效说明:在JVM垃圾接纳运行时,弱引用被终止.
WeakReference ref = new WeakReference(new MyDate());
System.gc();
等同于:
MyDate date = new MyDate();
// 垃圾接纳
If(JVM.内存不敷()) {
date = null;
System.gc();
}
3. 4 假象引用
示例代码:
package com.skywang.java; import java.lang.ref.ReferenceQueue; import java.lang.ref.PhantomReference; public class PhantomReferenceTest { public static void main(String[] args) { ReferenceQueue queue = new ReferenceQueue(); PhantomReference ref = new PhantomReference(new MyDate(), queue); System.gc(); } }
运行功效:
obj [Date: 1372142282558] is gc
功效说明:假象引用,在实例化后,就被终止了。
ReferenceQueue queue = new ReferenceQueue();
PhantomReference ref = new PhantomReference(new MyDate(), queue);
System.gc();
等同于:
MyDate date = new MyDate();
date = null;
可以用以下表格总结上面的内容:
点击下载:源代码