本文的示例中需要触发垃圾回收,用了 Java 如何触发垃圾回收 给出的方法。
强引用
我们通常写的将对象赋值给变量,都是强引用。
public class Main {
static class Person {
String name;
public Person(String name) {
this.name = name;
}
@Override
public String toString() {
return "name=" + name;
}
}
public static void main(String[] args) {
Person ltt = new Person("ltt"); // ltt 变量对这个 Person 对象进行了强引用
System.out.println(ltt);
System.gc();
System.runFinalization();
System.out.println(ltt); // gc 后,被强引用的对象还在
}
}
输出:
name=ltt
name=ltt
软引用 SoftReference
当一个对象没有强引用,但有弱引用时,如果JVM内存不足,会将该对象回收。
import java.lang.ref.SoftReference;
public class Main {
static class Person {
String name;
public Person(String name) {
this.name = name;
}
@Override
public String toString() {
return "name=" + name;
}
}
public static void main(String[] args) {
Person ltt = new Person("ltt");
System.out.println(ltt); // name=ltt
SoftReference<Person> lttRef = new SoftReference<>(ltt); // lttRef 对 Person 对象进行弱引用
ltt = null; // 去掉对 Person 对象的强引用
System.out.println(lttRef.get()); // name=ltt
System.gc();
System.runFinalization();
// 因为内存尚充足,所以 Person 对象还在
System.out.println(lttRef.get()); // name=ltt
}
}
输出:
name=ltt
name=ltt
name=ltt
弱引用 WeakReference
当一个对象只有弱引用时,gc时会把该对象回收。
import java.lang.ref.WeakReference;
public class Main {
static class Person {
String name;
public Person(String name) {
this.name = name;
}
@Override
public String toString() {
return "name=" + name;
}
}
public static void main(String[] args) {
Person ltt = new Person("ltt");
System.out.println(ltt); // name=ltt
WeakReference<Person> lttRef = new WeakReference<>(ltt);
ltt = null;
System.out.println(lttRef.get()); // name=ltt
System.gc();
System.runFinalization();
// 被回收了,所以下面输出 null
System.out.println(lttRef.get()); // null
}
}
输出:
name=ltt
name=ltt
null
幽灵引用
如果一个对象只有幽灵引用,相当于没有任何引用,我们再也找不到它。在gc时,该对象会被回收。
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
public class Main {
static class Person {
String name;
public Person(String name) {
this.name = name;
}
@Override
public String toString() {
return "name=" + name;
}
}
public static void main(String[] args) {
Person ltt = new Person("ltt");
System.out.println(ltt); // name=ltt
ReferenceQueue queue = new ReferenceQueue();
PhantomReference<Person> lttRef = new PhantomReference<>(ltt, queue);
ltt = null;
// 没有 gc 也找不到对象了
System.out.println(lttRef.get()); // null
}
}
运行输出:
name=ltt
null
null
关于 ReferenceQueue,可以参考 Java ReferenceQueue 。