前言
相关文章:
【JVM】引用计数和可达性分析算法详解
无论是通过引用计数算法判断对象的引用数量,还是通过可达性分析算法判断对象是否引用链可达,判定对象是否存活都和“引用”离不开关系。在JDK 1.2版之前,Java里面的引用是很传统的定义: 如果reference类型的数据中存储的数值代表的是另外一块内存的起始地址,就称该reference数据是代表 某块内存、某个对象的引用。
在JDK 1.2版之后,Java对引用的概念进行了扩充,将引用分为强引用(Strongly Re-ference)、软引用(Soft Reference)、弱引用(Weak Reference)和虚引用(Phantom Reference)4种,这4种引用强度依次逐渐减弱。
强引用
无论任何情况下,只要强引用关系还存在,垃圾收集器就永远不会回收掉被引用的对象。
例如:
Object object = new Object();
显示地将引用赋值为null会中断强引用和某个对象之间的关联,JVM在合适的时间就会回收该对象(Vector类的clear方法中就是通过将引用赋值为null来实现清理工作的)。
object = null;
软引用
只被软引用关联着的对象,在系统将要发生内 存溢出异常前,会把这些对象列进回收范围之中进行第二次回收,如果这次回收还没有足够的内存, 才会抛出内存溢出异常。在JDK 1.2版之后提供了SoftReference类来实现软引用。
例如:
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.List;
/**
* -Xmx18m -verbose:gc
*/
public class SoftRefence {
public static void main(String[] args) {
int _1MB = 1024 * 1024;
List<SoftReference> list = new ArrayList<>();
for (int i = 0; i < 5; i++) {
SoftReference reference = new SoftReference(new byte[5 * _1MB]);
System.out.println(reference.get());
list.add(reference);
}
//循环打印软引用对象
for (SoftReference reference : list) {
System.out.println(reference.get());
}
}
}
jvm参数设置:
-Xmx18m -verbose:gc
输出结果:
[B@404b9385
[B@6d311334
[GC (Allocation Failure) 13205K->11297K(17920K), 0.0098332 secs]
[GC (Allocation Failure) 11297K->11281K(17920K), 0.0038346 secs]
[Full GC (Allocation Failure) 11281K->11208K(17920K), 0.0218753 secs]
[GC (Allocation Failure) 11208K->11208K(17920K), 0.0349663 secs]
[Full GC (Allocation Failure) 11208K->951K(14336K), 0.0100014 secs]
[B@682a0b20
[B@3d075dc0
[GC (Allocation Failure) 11348K->11287K(17920K), 0.0030580 secs]
[Full GC (Ergonomics) 11287K->11041K(17920K), 0.0252398 secs]
[GC (Allocation Failure) 11041K->11041K(17920K), 0.0020519 secs]
[Full GC (Allocation Failure) 11041K->800K(13824K), 0.0082546 secs]
[B@214c265e
null
null
null
null
[B@214c265e
只有最后一个有地址,前面四个都被垃圾回收了。
弱引用
被弱引用关联的对象只能生存到下一次垃圾收集发生为止。当垃圾收集器开始工作,无论当前内存是否足够,都会回收掉只 被弱引用关联的对象。在JDK 1.2版之后提供了WeakReference类来实现弱引用。
例如:
public class WeakReference {
public static void main(String[] args) {
java.lang.ref.WeakReference<String> str = new java.lang.ref.WeakReference<>(new String("sanxingtongxue"));
System.out.println(str.get());
System.gc();
System.out.println(str.get());
}
}
输出结果:
sanxingtongxue
null
弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被JVM回收,这个软引用就会被加入到与之关联的引用队列中。
虚引用
也称为“幽灵引用”或者“幻影引用”,它是最弱的一种引用关系。一个对象是否有虚引用的 存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚 引用关联的唯一目的只是为了能在这个对象被收集器回收时收到一个系统通知。在JDK 1.2版之后提供 了PhantomReference类来实现虚引用。
例如:
public static void main(String args[]) {
ReferenceQueue<String> queue = new ReferenceQueue<String>();
PhantomReference<String> str = new PhantomReference<String>(new String("sanxingtongxue"), queue);
System.out.println(str.get());
}
结果:
null
虚引用不能单独使用,必须配合引用队列一起使用。
点赞 收藏 关注