java中的引用类型
java中的引用类型
在包java.lang.ref
下面声明了一系列的java引用类型,作用主要是跟GC相关
强引用 StongReference
最常用的、默认的引用类型
1
Object o = new Object();
软引用 SoftReference
软引用的强度是仅次于强引用的,如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它; 如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。 软引用可用来实现内存敏感的高速缓存
1
2
3
4
5
6
String str=new String("abc");
SoftReference<String> softRef = new SoftReference<>(str);
str = null;
System.out.println(softRef.get());
System.gc();
System.out.println(softRef.get());
弱引用 WeakReference
弱引用的强度比软引用更次,也就是说只具有弱引用的对象拥有更短暂的生命周期。 在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。 不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。 如果这个对象是偶尔的使用,并且希望在使用时随时就能获取到,但又不想影响此对象的垃圾收集,那么你应该用 WeakReference
来标记此对象。
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
@Test
public void weakReference2() {
int size = 3;
LinkedList<WeakReference<VeryBig>> weakList = new LinkedList<WeakReference<VeryBig>>();
for (int i = 0; i < size; i++) {
weakList.add(new VeryBigWeakReference(new VeryBig("Weak " + i), rq));
System.out.println("Just created weak: " + weakList.getLast());
}
System.gc();
try { // 下面休息几分钟,让上面的垃圾回收线程运行完成
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(weakList.size());
System.out.println(weakList);
checkQueue();
}
private static ReferenceQueue<VeryBig> rq = new ReferenceQueue<VeryBig>();
public static void checkQueue() {
Reference<? extends VeryBig> ref = null;
while ((ref = rq.poll()) != null) {
if (ref != null) {
System.out.println("In queue: " + ((VeryBigWeakReference) (ref)).id);
}
}
}
@ToString(callSuper = false)
class VeryBig {
public String id;
// 占用空间,让线程进行回收
@ToString.Exclude
byte[] b = new byte[1 << 10 << 10];
public VeryBig(String id) {
this.id = id;
}
protected void finalize() {
System.out.println("Finalizing VeryBig " + id);
}
}
class VeryBigWeakReference extends WeakReference<VeryBig> {
public String id;
public VeryBigWeakReference(VeryBig big, ReferenceQueue<VeryBig> rq) {
super(big, rq);
this.id = big.id;
}
protected void finalize() {
System.out.println("Finalizing VeryBigWeakReference " + id);
}
@Override
public VeryBig get() {
return super.get();
}
@Override
public String toString() {
return "VeryBigWeakReference{" +
"id='" + id + '\'' + ", VeryBig=" + get() +
'}';
}
}
上面的代码执行完了之后有个非常神奇的效果,WeakReference
引用的对象还在,但是Value
却是null,被GC了。 所以被GC的判断条件应该是只要引用链上存在弱引用就会被GC,除非有一个强引用指向这个对象。
虚引用 PhantomReference
1
2
3
4
5
6
7
8
9
10
11
// JDK源码注释
/**
* Returns this reference object's referent. Because the referent of a
* phantom reference is always inaccessible, this method always returns
* {@code null}.
*
* @return {@code null}
*/
public T get() {
return null;
}
虚引用相对来说比较怪异,因为你不管怎么get
都是null
,而且必须关联引用队列。
虚引用主要用来跟踪对象被垃圾回收的活动。
当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象之前,把这个虚引用加入到与之关联的引用队列中。
程序如果发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。
https://cloud.tencent.com/developer/article/1843330
本文由作者按照 CC BY 4.0 进行授权