Java中4种引用类型

对象

执行 new 指令之后会接着把对象按照程序员的意愿进行初始化(构造方法)。

  • 在 HotSpot 虚拟机中,对象在内存中存储的布局可以分为 3 块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。
  • 对象头包括两部分信息,第一部分用于存储对象自身的运行时数据,如哈希码(HashCode)、GC 分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。
  • 对象头的另外一部分是类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。
  • 如果对象是一个 java数组,那么在对象头中还有一块用于记录数组长度的数据。
  • 第三部分对齐填充并不是必然存在的,也没有特别的含义,它仅仅起着占位符的作用。由于 HotSpot VM 的自动内存管理系统要求对对象的大小必须是8 字节的整数倍。当对象其他数据部分没有对齐时,就需要通过对齐填充来补全。

对象类型

强引用

1
2
3
Reference r = new Reference();//强引用
r = null; // 清空引用
System.gc(); // r 将被回收

引用不存在时候,对象将会被回收

软引用

1
2
3
4
SoftReference<byte[]> sr = new SoftReference(new byte[1024 * 1024 * 10]);//软引用
System.gc();//内存足够时候,对象不会被回收

byte[] data = new byte[1024 * 1024 * 15];//创建新对象,可能会导致JVM内存不足,则将回收软引用对象

JVM内存空间不足时候,将会回收软引用对象

弱引用

1
2
WeakReference<Reference> wr = new WeakReference<>(new Reference());//弱引用
System.gc();//弱引用遇到GC时候,将会被回收

弱引用遇到GC时候,对象将会被回收

虚引用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class Reference {

protected void finalize() throws Throwable {
System.out.println("Object finalize...");
}

private static List<Object> LIST = new ArrayList<>();
private static ReferenceQueue<Reference> QUEUE = new ReferenceQueue();

public static void main(String[] args) {
PhantomReference<Reference> ref = new PhantomReference<>(new Reference(), QUEUE);//虚引用被回收的时候,将会把对象放入队列里面去

new Thread(() -> {
while (true) {
LIST.add(new byte[1024 * 1024]);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(ref.get());
}
}).start();


new Thread(() -> {
while (true) {
final java.lang.ref.Reference<? extends Reference> poll = QUEUE.poll();
if (poll != null) {//虚引用被回收时候,将会被监听到
System.out.println("虚引用被回收了...");
}
}
}).start();


try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.gc();
}
}

主要用在虚拟机层,管理堆外内存使用。不能单独使用,主要是用于追踪对象被垃圾回收的状态。通过PhantomReference类和引用队列ReferenceQueue类联合使用实现。

Author: suce
Link: https://haoubox.cn/2021/06/11/Java中4种引用类型/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.