进行垃圾回收时,无论是使用引用计数算法还是使用可达性分析算法,判断对象存活都和“引用”离不开关系。在JDK 1.2前,Java里面的引用是很传统的定义:如果reference类型的数据中存储的数值代表的是另外一块内存的起始地址,就称该reference数据是代表某块内存、某个对象的引用。在JDK 1.2后,Java对引用的概念进行了扩充,将引用分为强引用、软引用、弱引用和虚引用。
强引用
- 强引用是最普遍的引用。例如,Object obj = new Object()中,obj就是一个强引用
- 任何情况下,只要强引用关系还存在,被引用的对象就不会被垃圾回收
- 显式的设置强引用对象为null,可以解除这个对象的强引用
软引用
- 软引用对象在内存充足时,不会被垃圾回收;在垃圾回收后,若内存空间不充足,则软引用对象会被垃圾回收
- 可以配合引用队列来释放软引用本身
- jdk1.2后提供SoftReference类来实现软引用
- 软引用适用于创建缓存
/**
* 演示软引用
* 运行时加上jvm参数:-Xmx20m -XX:+PrintGCDetails -verbose:gc
*/
public class TestSoftReference {
private static final int _4MB = 4 * 1024 * 1024;
public static void main(String[] args) throws IOException {
soft();
}
public static void soft() {
List<SoftReference<byte[]>> list = new ArrayList<>();
for (int i = 0; i < 5; i++) {
//创建软引用对象,使得当内存不足时,回收这些对象
SoftReference<byte[]> ref = new SoftReference<>(new byte[_4MB]);
System.out.println(ref.get());
list.add(ref);
System.out.println(list.size());
}
System.out.println("循环结束:" + list.size());
for (SoftReference<byte[]> ref : list) {
System.out.println(ref.get());
}
}
}
弱引用
- 弱引用对象比软引用对象生命周期更短暂
- 进行垃圾回收时,无论内存是否充足,弱引用对象都会被回收
- 可以配合引用队列来释放弱引用本身
- jdk1.2后提供WeakReference类来实现弱引用
- 弱引用可以用来实现缓存,如弱哈希表;弱引用还可以用来解决循环引用的问题
/**
* 测试弱引用
* 运行时加上jvm参数:-Xmx20m -XX:+PrintGCDetails -verbose:gc
*/
public class TestWeakReference {
private static final int _4MB = 4 * 1024 * 1024;
public static void main(String[] args) {
List<WeakReference<byte[]>> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
//创建弱引用对象
WeakReference<byte[]> ref = new WeakReference<>(new byte[_4MB]);
list.add(ref);
for (WeakReference<byte[]> w : list) {
System.out.print(w.get()+" ");
}
System.out.println();
}
System.out.println("循环结束:" + list.size());
}
}
虚引用
- 虚引用完全不影响对象的生命周期,任何时候都可能会被垃圾回收
- 必须配合引用队列使用,主要配合ByteBuffer使用
- 当一个对象被垃圾回收时,若该对象有虚引用,则会在回收前将虚引用加入到引用队列中
- jdk1.2后提供PhantomReference类来实现虚引用
- 虚引用主要用来跟踪垃圾回收器回收垃圾的活动
String str = new String("abc");
//创建引用队列
ReferenceQueue queue = new ReferenceQueue();
// 创建虚引用,要求必须与一个引用队列关联
PhantomReference pr = new PhantomReference(str, queue);
总结
引用类型 | 垃圾回收时间 | 用途 | 生存时间 | 引用强度 |
---|---|---|---|---|
强引用 | 从来不会 | 对象的一般状态 | JVM停止运行时终止 | 最强 |
软引用 | 内存不足时 | 对象缓存 | 内存不足时终止 | 中 |
弱引用 | 正常垃圾回收时 | 对象缓存 | 垃圾回收后终止 | 弱 |
虚引用 | 正常垃圾回收时 | 跟踪对象的垃圾回收 | 垃圾回收后终止 | 最弱 |