Java中没有指针,到处都是引用(除了基本类型)。所以,当然,你肯定知道java的引用,并用了很久,但是是不是对此了解地比较全面?而这些引用有什么作用,且有什么不同呢?
Java中有个java.lang.ref包,这里面都是描述引用对象的,包括了Reference,SoftReference,WeakReference和PhantomReference。其中,Reference是基类其他三个类的基类。下面就这几种引用对象做个说明。
强引用(Strong References)
我们每天都在用强引用(如果你每天都在用java的话),一段如下的代码:
HashMap mapRef = new HashMap();
就是通过new HashMap();创建了一个对象(这东西在heap上),并把一个强引用存到了 mapRef引用中。而强引用之为“强”的地方就在于其对垃圾回收器所产生的影响。如果一个对象可以经由一条强引用链可达(也就说这个对象是Strongly reachable),那么就说明这个类不适合被垃圾回收。我们也绝对不希望正在使用的对象一下子了无踪迹了。
但是强引用会对我们的应用产生很“强”的影响。比如:经常会碰到一个问题,缓存。通过Set(以set为例吧)模拟的缓存,在应用运行的过程中,会不断有 大量对象添加到set中。这些对象并不会被GC回收,并且随着对象的增多,我们的内存也会不断变大,终于有一天OutOfMemory啦。其实,set可 能使用频率还不大,HashMap的key-value模式让我们爱不释手,引诱着你去不断地put,put,扑通。。OutOfMemory啦。
对于java这门有魅力,有活力,有朝气,有老气,有垃圾自动回收机制的语言而言,我们不应被上述问题所困扰。
弱引用(Weak Reference)
弱引用,就是不是那种用强制的方式要求对象存在于内存的引用。可以借助垃圾回收器来判断某个对象的可达性,并帮你回收弱引用所引用的对象。如何创建一个弱引用呢:
StringBuffer sbuff = new StringBuffer("What is a WeakReference?");
WeakReference<StringBuffer> wref = new WeakReference<StringBuffer>(sbuff);
sbbuff=null;//这里的操作,看情况定。在这里主要为了说明,原来强引用的一个对象,被转成一个弱引用来指向。
然后通过wref.get()来获取sbuff对象。因为弱引用并没强悍到可以阻止垃圾回收器回收wref引用的对象(这里要区分引用对象和被引用的对象,在创建一个 WeakReference时,就有一个引用对象诞生了,它指向了一个被引用的对象),所以可能从某一刻开始,wref.get()就开始给我们null了。
对于上面提到的使用HashMap时,对象过多(并且不删除,而被垃圾回收)会造成的OutOfMemory问题,可以通过WeakHashMap来实现,这样垃圾回收器就会帮我们处理那些时间长了不用,还占地方的类了,而不至于出现OutOfMemory问题。
引用队列(
ReferenceQueue,何方神圣?)
当WeakReference开始返回null时,说明它原来指向的对象已经变成了垃圾。另外也说明这个WeakReference对我们已经没多少用处了。我们需要做点什么来处理这些没用的东西?
逢此危难之际,ReferenceQueue闪亮登场。据官方资料,其定义为:
Reference queues, to which registered reference objects are appended by the garbage collector after the appropriate reachability changes are detected.
(当检测到相应的可达性发生改变后,垃圾回收器就会将注册有此队列的引用对象添加到这个引用队列中。)
如何注册一个队列?在WeakReference的构造函数中,有一个WeakReference(T referent, ReferenceQueue<? super T> q)。所以,当一个WeakReference变成一个死引用时,它就会被添加到这个
ReferenceQueue中,只要定期的来处理一下这个ReferenceQueue就可以了。
不同的引用
引用实际上是有好几种的,就如我们在java.lang.ref包中看到的那样,再加上强引用,有4种引用类型:强(Strong)、软(Soft)、弱(Weak)、幻象(Phantom),引用依次从强到弱。接下来,就看看其他的引用。
软引用(Soft Reference)
软引用,跟弱引用功能挺像的。但是软引用指向的对象一般会比弱引用的存活时间长一些,直到内存空间不够时,才会被垃圾回收。一个Weakly reachable对象,是仅仅被WeakReference引用的,并且会被垃圾回收器在下一个垃圾回收周期中丢弃;而一个Softly reachable对象,则会活地时间长一些。
软引用给我们带来了很大的实惠,尤其是缓存的实现。比如,我们有一个缓存池,对于内存比较紧张的情况来说,一旦要达到memory上限时,垃圾回收器就将Soft Reference引用的对象释放掉,以避免OutOfMemory惨剧的发生。
幻象引用(Phantom Reference)
幻象引用,是不同于Soft和Weak的引用。幻象引用对指向对象的引用强度如此之脆弱,以至于调用方法get()时,总是返回null。它的主要作用就是跟踪所指向的对象已经dead了,那么其跟WeakReference的区别是什么呢?
它们的区别就在于:是在什么时候,这个引用对象被添加到引用队列中的。WeakReference是在当其所引用的对象变成Weakly Reachable时被添加到引用队列中的,这发生在一个对象被finalization或被垃圾回收之前的。理论上讲,一个对象在被finalize()时,是可以被“复活”的,但此时WeakReference已经没活力了。对幻象引用来说,只有当其所引用的对象被彻底垃圾回收(从内存中消除)时,才会添加到引用队列中。而幻象引用的get方法总是返回null,就是要避免我们来“复活”一个奄奄一息的对象。
那么幻象引用有何实际作用?
第一、我们可以在监控一个对象什么时候被彻底销毁了。那样,就可以做点什么其他事情(看你是不是有这方面的需求啦)。不过实际中,这种情况也不多的。
第二、因为理论上存在的,可以通过一个对象的finalize()方法“复活”一个对象,那么如果在一次垃圾回收处理时,调用了一个对象的finalize()(这个方法在何时调用不确定),却让它复活了。要再苦苦等待finalize()的执行,还不知道要到猴年马月的(天下大赦可以有,但不是天天有。谁知道啥时候天朝更替,人主易位)。突然就出现了OutOfMemory错误了。
而幻象引用绝对不会再让对象复活,只要被它逮着了,事情就简单了:挂定了!
总而言之,言而总之,归根结底:
引用是关系垃圾回收的。
转载自:http://www.cnblogs.com/ericchen/
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
import
java.lang.ref.PhantomReference;
import
java.lang.ref.Reference;
import
java.lang.ref.ReferenceQueue;
import
java.lang.ref.SoftReference;
import
java.lang.ref.WeakReference;
import
java.util.ArrayList;
import
java.util.Arrays;
import
java.util.Collection;
import
java.util.Collections;
import
java.util.HashSet;
import
java.util.LinkedList;
import
java.util.List;
import
java.util.Set;
class
VeryBig{
private
static
final
int
SIZE =
10000
;
private
long
[] la =
new
long
[SIZE];
private
String ident;
public
VeryBig(String id) {
ident = id;
}
@Override
public
String toString() {
return
ident;
}
protected
void
finalize() {
System.out.println(
"finalize...."
+ ident);
}
}
public
class
Test{
private
static
ReferenceQueue<VeryBig> rq =
new
ReferenceQueue<VeryBig>();
public
static
void
checkQueue() {
Reference<?
extends
VeryBig> inq = rq.poll();
if
(inq !=
null
) {
System.out.println(
"in Queue : "
+ inq.get());
}
}
public
static
void
main(String[] args) {
int
size =
10
;
System.out.println(
"--------Soft------------"
);
LinkedList<SoftReference<VeryBig>> sa =
new
LinkedList<SoftReference<VeryBig>>();
for
(
int
i =
0
; i < size; ++i) {
sa.add(
new
SoftReference<VeryBig>(
new
VeryBig(
"soft"
+ i), rq));
System.out.println(
"just created soft: "
+ sa.getLast().get());
checkQueue();
}
SoftReference<VeryBig> s =
new
SoftReference<VeryBig>(
new
VeryBig(
"soft"
));
System.out.println(
"--------Weak------------"
);
LinkedList<WeakReference<VeryBig>> wa =
new
LinkedList<WeakReference<VeryBig>>();
for
(
int
i =
0
; i < size; ++i) {
wa.add(
new
WeakReference<VeryBig>(
new
VeryBig(
"weak"
+ i), rq));
System.out.println(
"just create weak : "
+ wa.getLast().get());
checkQueue();
}
WeakReference<VeryBig> w =
new
WeakReference<VeryBig>(
new
VeryBig(
"Weak"
));
System.gc();
LinkedList<PhantomReference<VeryBig>> pa =
new
LinkedList<PhantomReference<VeryBig>>();
for
(
int
i =
0
; i < size; ++i) {
pa.add(
new
PhantomReference<VeryBig>(
new
VeryBig(
"phantom "
+ i), rq));
System.out.println(
"just create Phantom : "
+ pa.getLast().get());
checkQueue();
}
}
}
输出:
--------Soft------------
just created soft: soft0
just created soft: soft1
just created soft: soft2
just created soft: soft3
just created soft: soft4
just created soft: soft5
just created soft: soft6
just created soft: soft7
just created soft: soft8
just created soft: soft9
--------Weak------------
just create weak : weak0
just create weak : weak1
just create weak : weak2
just create weak : weak3
just create weak : weak4
just create weak : weak5
just create weak : weak6
just create weak : weak7
just create weak : weak8
just create weak : weak9
just create Phantom :
null
just create Phantom :
null
finalize....weak2
finalize....Weak
in Queue :
null
finalize....weak9
just create Phantom :
null
finalize....weak8
in Queue :
null
finalize....weak7
just create Phantom :
null
finalize....weak6
finalize....weak5
finalize....weak4
finalize....weak3
finalize....weak1
finalize....weak0
in Queue :
null
just create Phantom :
null
in Queue :
null
just create Phantom :
null
in Queue :
null
just create Phantom :
null
in Queue :
null
just create Phantom :
null
in Queue :
null
just create Phantom :
null
in Queue :
null
just create Phantom :
null
in Queue :
null
|