本文转载于https://www.cn blogs.com/skywang 12345/p/3154474.html
1 Java引用介绍从1.2版开始,Java引入了四种类型的引用,这四种类型的引用按从高到低的顺序排列:
强引用 软引用 弱引用 虚引用
强引用(StrongReference)
强烈的引用是使用最普遍的引用。 如果对象具有强引用,则垃圾收集器不会回收该对象。 如果内存空间不足,Java虚拟机希望抛出OutOfMemoryError错误并异常终止程序。 此外,不会通过随意重用具有强引用的对象来解决内存不足的问题。
软引用(SoftReference)
如果对象只有软引用,则内存空间足够,垃圾回收器不会回收它; 如果内存空间不足,则会回收这些对象的内存。 只要垃圾回收器没有回收它,该对象就可以在程序中使用。 软引用可用于实现对内存敏感的缓存。
可将软参照与“参照队列”(ReferenceQueue )结合使用。 当垃圾回收器回收可变引用所引用的对象时,Java虚拟机会将其添加到关联的引用队列中。
弱引用(WeakReference)
弱参照与弱参照之间的区别在于只有弱参照的对象具有较短的生命周期。 如果在扫描垃圾收集器线程管理的内存空间时遇到只包含弱引用的对象,则无论当前内存空间是否足够,都将回收该内存。 但是,由于垃圾收集器是低优先级线程,因此无法立即找到只有弱引用的对象。
弱引用可以与“引用队列”(ReferenceQueue )结合使用。 当对弱引用所引用的对象进行垃圾回收时,Java虚拟机会将弱引用添加到关联的引用队列中。
虚引用(PhantomReference)
“虚引用”单身金鱼,形同虚设,与其他几种引用不同,虚引用并不决定对象的生命周期。 如果一个对象只有虚构的引用,它随时都可能被垃圾回收回收,就像没有任何引用一样。
虚引用主要用于跟踪回收到垃圾回收器中的对象的活动。 虚参考、软参考和弱参考的一个区别在于,虚参考必须与参考队列结合使用。 如果垃圾收集器尝试回收对象时发现仍有虚拟引用,请在回收对象的内存之前将其添加到关联的引用队列中。
因为引用和内存回收的关系密切。 然后,首先通过实例了解内存回收。 并进一步引用实例以加深对引用的理解。
2内存回收
创建公共类MyDate表示finalize (起到了覆盖函数的作用。 finalize ) )输出打印信息,以便于跟踪。
描述: finalize ) )函数在JVM回收内存时执行,但不保证JVM在回收内存时一定会调用finalize ) )。
我的日期代码如下所示。
package com.skywang.java; import java.util.Date; publicclassmydateextendsdate {/* * createsanewinstanceofmydate */public my date (}//finalize ) )方法protectedvoidfinate }公共字符串状态() { return 'Date: ' this.getTime ); }
该类扩展了java.util.Date类,并重写了finalize (和toString )方法。
创建公共类ReferenceTest旨在定义方法drainMemory ()。 这意味着,通过消耗大量内存,JVM可以回收内存。
参考测试代码如下所示。
package com.skywang.java; publicclassreferencetest {/* * createsanewinstanceofreferencetest */publicreferencetest ({ }//消耗大量内存
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:显式调用垃圾回收
实现代码:
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(); }}运行结果:
<无任何输出>
结果说明:即使显式调用了垃圾回收,但是用于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;
可以用以下表格总结上面的内容:
级别
什么时候被垃圾回收
用途
生存时间
强引用
从来不会
对象的一般状态
JVM停止运行时终止
软引用
在内存不足时
对象简单?缓存
内存不足时终止
弱引用
在垃圾回收时
对象缓存
gc运行后终止
虚引用
Unknown
Unknown
Unknown