Java四种引用方式
强引用
class TestReference{
// 方便垃圾回收时显示
@Override
protected void finalize() throws Throwable {
System.out.println("finalize");
}
}
public static void main(String[] args) {
// 强引用
TestReference ref = new TestReference();
System.out.println(ref);
System.gc();
System.out.println(ref);
}
当主动调用垃圾回收时,强引用不会被回收。
软引用
public static void main(String[] args) {
SoftReference<byte[]> ref =
new SoftReference<>(new byte[1024 * 1024 * 5]);
System.out.println(ref.get());
System.gc();
System.out.println(ref.get());
byte[] buffer = new byte[1024 * 1024 * 10];
System.out.println(ref.get());
}
形如new byte[]的是软引用,未赋值到某个变量,软引用当堆内存足够时不会被垃圾回收,但是当内存空间不够时会被回收。
下面是运行结果,设置了堆最大为15M。使用-Xmx参数设置。
[B@1540e19d
[B@1540e19d
null
弱引用
public static void main(String[] args) {
WeakReference<TestReference> ref =
new WeakReference<>(new TestReference());
System.out.println(ref.get());
System.gc();
System.out.println(ref.get());
}
弱引用当垃圾回收发生时,无论堆内存是否足够则都会被回收。
下面运行结果。
com.test.TestReference@1540e19d
null
finalize
虚引用
虚引用的使用需要搭配引用队列来使用,下面例子创建了一个虚引用,但是通过get()方法无法获取引用值,当虚引用被回收后,会进入引用队列中。
private static final List<Object> TEST_DATA =
new LinkedList<>();
private static final ReferenceQueue<TestReference> QUEUE = new ReferenceQueue<>();
public static void main(String[] args) {
TestReference obj = new TestReference();
// 虚引用
PhantomReference<TestReference> phantomReference = new PhantomReference<>(obj, QUEUE);
// 该线程不断读取这个虚引用,并不断往列表里插入数据,以促使系统早点进行GC
new Thread(() -> {
while (true) {
TEST_DATA.add(new byte[1024 * 100]);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
System.out.println(phantomReference.get());
}
}).start();
// 这个线程不断读取引用队列,当弱引用指向的对象呗回收时,该引用就会被加入到引用队列中
new Thread(() -> {
while (true) {
Reference<? extends TestReference> poll = QUEUE.poll();
if (poll != null) {
System.out.println("--- 虚引用对象被jvm回收了 ---- " + poll);
System.out.println("--- 回收对象 ---- " + poll.get());
}
}
}).start();
obj = null;
try {
Thread.currentThread().join();
} catch (InterruptedException e) {
e.printStackTrace();
System.exit(1);
}
}
虚引用参考博客: https://www.cnblogs.com/mfrank/p/9837070.html
总结
4种引用由强到弱分别是强引用、软引用、弱引用、虚引用,软引用可用于缓冲,当内存空间不足时自动回收。虚引用可以用于做堆外内存的释放。
理解有限,如果有不对的地方还望指正。