沧海一粟

天下事有难易乎?为之,则难者亦易矣;不为,则易者亦难矣。

0%

Java里的引用

什么是Java里的引用

引用可以理解为指针

有什么用

不同引用不同用途
强引用
软引用
弱引用
虚引用

Java中引用实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package java.lang.ref;

import jdk.internal.vm.annotation.ForceInline;
import jdk.internal.HotSpotIntrinsicCandidate;
import jdk.internal.access.JavaLangRefAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.ref.Cleaner;

/**
* Abstract base class for reference objects. This class defines the
* operations common to all reference objects. Because reference objects are
* implemented in close cooperation with the garbage collector, this class may
* not be subclassed directly.
*
* @author Mark Reinhold
* @since 1.2
*/

public abstract class Reference<T> {

}
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/* The state of a Reference object is characterized by two attributes.  It
* may be either "active", "pending", or "inactive". It may also be
* either "registered", "enqueued", "dequeued", or "unregistered".
*
* Active: Subject to special treatment by the garbage collector. Some
* time after the collector detects that the reachability of the
* referent has changed to the appropriate state, the collector
* "notifies" the reference, changing the state to either "pending" or
* "inactive".
* referent != null; discovered = null, or in GC discovered list.
*
* Pending: An element of the pending-Reference list, waiting to be
* processed by the ReferenceHandler thread. The pending-Reference
* list is linked through the discovered fields of references in the
* list.
* referent = null; discovered = next element in pending-Reference list.
*
* Inactive: Neither Active nor Pending.
* referent = null.
*
* Registered: Associated with a queue when created, and not yet added
* to the queue.
* queue = the associated queue.
*
* Enqueued: Added to the associated queue, and not yet removed.
* queue = ReferenceQueue.ENQUEUE; next = next entry in list, or this to
* indicate end of list.
*
* Dequeued: Added to the associated queue and then removed.
* queue = ReferenceQueue.NULL; next = this.
*
* Unregistered: Not associated with a queue when created.
* queue = ReferenceQueue.NULL.
*
* The collector only needs to examine the referent field and the
* discovered field to determine whether a (non-FinalReference) Reference
* object needs special treatment. If the referent is non-null and not
* known to be live, then it may need to be discovered for possible later
* notification. But if the discovered field is non-null, then it has
* already been discovered.
*
* FinalReference (which exists to support finalization) differs from
* other references, because a FinalReference is not cleared when
* notified. The referent being null or not cannot be used to distinguish
* between the active state and pending or inactive states. However,
* FinalReferences do not support enqueue(). Instead, the next field of a
* FinalReference object is set to "this" when it is added to the
* pending-Reference list. The use of "this" as the value of next in the
* enqueued and dequeued states maintains the non-active state. An
* additional check that the next field is null is required to determine
* that a FinalReference object is active.
*
* Initial states:
* [active/registered]
* [active/unregistered] [1]
*
* Transitions:
* clear
* [active/registered] -------> [inactive/registered]
* | |
* | | enqueue [2]
* | GC enqueue [2] |
* | -----------------|
* | |
* v |
* [pending/registered] --- v
* | | ReferenceHandler
* | enqueue [2] |---> [inactive/enqueued]
* v | |
* [pending/enqueued] --- |
* | | poll/remove
* | poll/remove |
* | |
* v ReferenceHandler v
* [pending/dequeued] ------> [inactive/dequeued]
*
*
* clear/enqueue/GC [3]
* [active/unregistered] ------
* | |
* | GC |
* | |--> [inactive/unregistered]
* v |
* [pending/unregistered] ------
* ReferenceHandler
*
* Terminal states:
* [inactive/dequeued]
* [inactive/unregistered]
*
* Unreachable states (because enqueue also clears):
* [active/enqeued]
* [active/dequeued]
*
* [1] Unregistered is not permitted for FinalReferences.
*
* [2] These transitions are not possible for FinalReferences, making
* [pending/enqueued] and [pending/dequeued] unreachable, and
* [inactive/registered] terminal.
*
* [3] The garbage collector may directly transition a Reference
* from [active/unregistered] to [inactive/unregistered],
* bypassing the pending-Reference list.
*/

private T referent; /* Treated specially by GC */

/* The queue this reference gets enqueued to by GC notification or by
* calling enqueue().
*
* When registered: the queue with which this reference is registered.
* enqueued: ReferenceQueue.ENQUEUE
* dequeued: ReferenceQueue.NULL
* unregistered: ReferenceQueue.NULL
*/
volatile ReferenceQueue<? super T> queue;

/* The link in a ReferenceQueue's list of Reference objects.
*
* When registered: null
* enqueued: next element in queue (or this if last)
* dequeued: this (marking FinalReferences as inactive)
* unregistered: null
*/
@SuppressWarnings("rawtypes")
volatile Reference next;

/* Used by the garbage collector to accumulate Reference objects that need
* to be revisited in order to decide whether they should be notified.
* Also used as the link in the pending-Reference list. The discovered
* field and the next field are distinct to allow the enqueue() method to
* be applied to a Reference object while it is either in the
* pending-Reference list or in the garbage collector's discovered set.
*
* When active: null or next element in a discovered reference list
* maintained by the GC (or this if last)
* pending: next element in the pending-Reference list (null if last)
* inactive: null
*/
private transient Reference<T> discovered;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/* -- Referent accessor and setters -- */

/**
* Returns this reference object's referent. If this reference object has
* been cleared, either by the program or by the garbage collector, then
* this method returns {@code null}.
*
* @return The object to which this reference refers, or
* {@code null} if this reference object has been cleared
*/
@HotSpotIntrinsicCandidate
public T get() {
return this.referent;
}
1
2
3
4
5
6
7
8
9
10
/**
* Clears this reference object. Invoking this method will not cause this
* object to be enqueued.
*
* <p> This method is invoked only by Java code; when the garbage collector
* clears references it does so directly, without invoking this method.
*/
public void clear() {
this.referent = null;
}

强引用 StrongReference

强引用 Object obj = new Object();
上述Object这类对象就具有强引用,属于不可回收的资源,垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠回收具有强引用的对象,来解决内存不足的问题。
如果想中断或者回收强引用对象,可以显式地将引用赋值为null,这样的话JVM就会在合适的时间,进行垃圾回收。

软引用 SoftReference

如果一个对象只具有软引用,那么它的性质属于可有可无的那种。如果此时内存空间足够,垃圾回收器就不会回收它,如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。

软引用可用来实现内存敏感的告诉缓存。软引用可以和一个引用队列联合使用,如果软件用所引用的对象被垃圾回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。
当内存不足时,软引用对象被回收时,reference.get()为null,此时软引用对象的作用已经发挥完毕,这时将其添加进ReferenceQueue 队列中

1
2
3
4
5
Object obj = new Object();
ReferenceQueue queue = new ReferenceQueue();
SoftReference reference = new SoftReference(obj, queue);
//强引用对象滞空,保留软引用
obj = null;

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
/**
* Soft reference objects, which are cleared at the discretion of the garbage
* collector in response to memory demand. Soft references are most often used
* to implement memory-sensitive caches.
*
* <p> Suppose that the garbage collector determines at a certain point in time
* that an object is <a href="package-summary.html#reachability">softly
* reachable</a>. At that time it may choose to clear atomically all soft
* references to that object and all soft references to any other
* softly-reachable objects from which that object is reachable through a chain
* of strong references. At the same time or at some later time it will
* enqueue those newly-cleared soft references that are registered with
* reference queues.
*
* <p> All soft references to softly-reachable objects are guaranteed to have
* been cleared before the virtual machine throws an
* {@code OutOfMemoryError}. Otherwise no constraints are placed upon the
* time at which a soft reference will be cleared or the order in which a set
* of such references to different objects will be cleared. Virtual machine
* implementations are, however, encouraged to bias against clearing
* recently-created or recently-used soft references.
*
* <p> Direct instances of this class may be used to implement simple caches;
* this class or derived subclasses may also be used in larger data structures
* to implement more sophisticated caches. As long as the referent of a soft
* reference is strongly reachable, that is, is actually in use, the soft
* reference will not be cleared. Thus a sophisticated cache can, for example,
* prevent its most recently used entries from being discarded by keeping
* strong referents to those entries, leaving the remaining entries to be
* discarded at the discretion of the garbage collector.
*
* @author Mark Reinhold
* @since 1.2
*/

public class SoftReference<T> extends Reference<T> {

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* Returns this reference object's referent. If this reference object has
* been cleared, either by the program or by the garbage collector, then
* this method returns {@code null}.
*
* @return The object to which this reference refers, or
* {@code null} if this reference object has been cleared
*/
public T get() {
T o = super.get();
if (o != null && this.timestamp != clock)
this.timestamp = clock;
return o;
}

弱引用 WeakReference

如果一个对象具有弱引用,那其的性质也是可有可无的状态。

而弱引用和软引用的区别在于:弱引用的对象拥有更短的生命周期,只要垃圾回收器扫描到它,不管内存空间充足与否,都会回收它的内存。

同样的弱引用也可以和引用队列一起使用。

1
2
3
4
5
Object obj = new Object();
ReferenceQueue queue = new ReferenceQueue();
WeakReference reference = new WeakReference(obj, queue);
//强引用对象滞空,保留软引用
obj = null;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* Weak reference objects, which do not prevent their referents from being
* made finalizable, finalized, and then reclaimed. Weak references are most
* often used to implement canonicalizing mappings.
*
* <p> Suppose that the garbage collector determines at a certain point in time
* that an object is <a href="package-summary.html#reachability">weakly
* reachable</a>. At that time it will atomically clear all weak references to
* that object and all weak references to any other weakly-reachable objects
* from which that object is reachable through a chain of strong and soft
* references. At the same time it will declare all of the formerly
* weakly-reachable objects to be finalizable. At the same time or at some
* later time it will enqueue those newly-cleared weak references that are
* registered with reference queues.
*
* @author Mark Reinhold
* @since 1.2
*/

public class WeakReference<T> extends Reference<T> {

}

虚引用(PhantomReference)

虚引用和前面的软引用、弱引用不同,它并不影响对象的生命周期。如果一个对象与虚引用关联,则跟没有引用与之关联一样,在任何时候都可能被垃圾回收器回收。

注意:虚引用必须和引用队列关联使用,当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会把这个虚引用加入到与之关联的引用队列中。

程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。

1
2
3
4
5
Object obj = new Object();
ReferenceQueue queue = new ReferenceQueue();
PhantomReference reference = new PhantomReference(obj, queue);
//强引用对象滞空,保留软引用
obj = null;
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
package java.lang.ref;


/**
* Phantom reference objects, which are enqueued after the collector
* determines that their referents may otherwise be reclaimed. Phantom
* references are most often used to schedule post-mortem cleanup actions.
*
* <p> Suppose the garbage collector determines at a certain point in time
* that an object is <a href="package-summary.html#reachability">
* phantom reachable</a>. At that time it will atomically clear
* all phantom references to that object and all phantom references to
* any other phantom-reachable objects from which that object is reachable.
* At the same time or at some later time it will enqueue those newly-cleared
* phantom references that are registered with reference queues.
*
* <p> In order to ensure that a reclaimable object remains so, the referent of
* a phantom reference may not be retrieved: The {@code get} method of a
* phantom reference always returns {@code null}.
*
* @author Mark Reinhold
* @since 1.2
*/

public class PhantomReference<T> extends Reference<T> {

}
1
2
3
4
5
6
7
8
9
10
/**
* 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;
}