对象的四种引用关系–强 软 弱 虚
强引用:
public static void main(String[] args) throws IOException {
Object m = new Object();
System.gc(); //垃圾回收不了m
m = null;
System.gc(); //垃圾回收了m
}
- Object m = new Object(); m 和 new Object() 之间就是强引用
- 如果有强引用,垃圾回收不了
- 只有当对象没有引用了强引用才可以被回收
软引用:
假设内存只有20M
public static void main(String[] args) {
SoftReference<byte[]> m = new SoftReference<>(new byte[1024*1024*10]);
System.out.println(m.get());
System.gc();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(m.get());
//再分配一个数组,heap将装不下,这时候系统会垃圾回收,先回收一次,如果不够,会把软引用干掉
byte[] b = new byte[1024*1024*15];
System.out.println(m.get());
}
- 设置内存只有20M
- 先给软引用分配一个10M的空间
- 触发GC
- 还可以get()到,说明没有被回收
- 在创建一个15M的空间,超过了内存空间
- 软引用被回收调
- 软引用 只有在内存不够的情况下才会被垃圾回收机制回收
- 应用场景: 缓存
idea设置内存空间只有20M
弱引用:
public static void main(String[] args) {
WeakReference<M> m = new WeakReference<>(new M());
System.out.println(m.get());
System.gc();
System.out.println(m.get());
}
- 弱引用只要垃圾回收器一会收,他就被回收了
- ThreadLocal 代表案例
虚引用:
public class T04_PhantomReference {
private static final List<Object> LIST = new LinkedList<>();
private static final ReferenceQueue<M> QUEUE = new ReferenceQueue<>();
public static void main(String[] args) {
PhantomReference<M> phantomReference = new PhantomReference<>(new M(), QUEUE);
new Thread(() -> {
while (true) {
LIST.add(new byte[1024 * 1024]);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
System.out.println(phantomReference.get());
}
}).start();
new Thread(() -> {
while (true) {
Reference<? extends M> poll = QUEUE.poll();
if (poll != null) {
System.out.println("--- 虚引用对象被jvm回收了 ---- " + poll);
}
}
}).start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
- 虚引用组成: 一个对象 一个队列
- 虚引用当被垃圾回收器回收时,会把它放在query队列里面
应用场景:
- Buffer 指向的堆外内存(不受jvm管理)
- 当buffer被回收的时候,怎么回收对外内存呢?
- 他会检测queue中有没有值,有值的话,说明虚内存已经被回收了
- 所以就去回收堆外内存