41 * @since 1.2 |
41 * @since 1.2 |
42 */ |
42 */ |
43 |
43 |
44 public abstract class Reference<T> { |
44 public abstract class Reference<T> { |
45 |
45 |
46 /* A Reference instance is in one of four possible internal states: |
46 /* The state of a Reference object is characterized by two attributes. It |
47 * |
47 * may be either "active", "pending", or "inactive". It may also be |
48 * Active: Subject to special treatment by the garbage collector. Some |
48 * either "registered", "enqueued", "dequeued", or "unregistered". |
49 * time after the collector detects that the reachability of the |
49 * |
50 * referent has changed to the appropriate state, it changes the |
50 * Active: Subject to special treatment by the garbage collector. Some |
51 * instance's state to either Pending or Inactive, depending upon |
51 * time after the collector detects that the reachability of the |
52 * whether or not the instance was registered with a queue when it was |
52 * referent has changed to the appropriate state, the collector |
53 * created. In the former case it also adds the instance to the |
53 * "notifies" the reference, changing the state to either "pending" or |
54 * pending-Reference list. Newly-created instances are Active. |
54 * "inactive". |
55 * |
55 * referent != null; discovered = null, or in GC discovered list. |
56 * Pending: An element of the pending-Reference list, waiting to be |
56 * |
57 * enqueued by the Reference-handler thread. Unregistered instances |
57 * Pending: An element of the pending-Reference list, waiting to be |
58 * are never in this state. |
58 * processed by the ReferenceHandler thread. The pending-Reference |
59 * |
59 * list is linked through the discovered fields of references in the |
60 * Enqueued: An element of the queue with which the instance was |
60 * list. |
61 * registered when it was created. When an instance is removed from |
61 * referent = null; discovered = next element in pending-Reference list. |
62 * its ReferenceQueue, it is made Inactive. Unregistered instances are |
62 * |
63 * never in this state. |
63 * Inactive: Neither Active nor Pending. |
64 * |
64 * referent = null. |
65 * Inactive: Nothing more to do. Once an instance becomes Inactive its |
65 * |
66 * state will never change again. |
66 * Registered: Associated with a queue when created, and not yet added |
67 * |
67 * to the queue. |
68 * The state is encoded in the queue and next fields as follows: |
68 * queue = the associated queue. |
69 * |
69 * |
70 * Active: queue = ReferenceQueue with which instance is registered, or |
70 * Enqueued: Added to the associated queue, and not yet removed. |
71 * ReferenceQueue.NULL if it was not registered with a queue; next = |
71 * queue = ReferenceQueue.ENQUEUE; next = next entry in list, or this to |
72 * null. |
72 * indicate end of list. |
73 * |
73 * |
74 * Pending: queue = ReferenceQueue with which instance is registered; |
74 * Dequeued: Added to the associated queue and then removed. |
75 * next = this |
75 * queue = ReferenceQueue.NULL; next = this. |
76 * |
76 * |
77 * Enqueued: queue = ReferenceQueue.ENQUEUED; next = Following instance |
77 * Unregistered: Not associated with a queue when created. |
78 * in queue, or this if at end of list. |
78 * queue = ReferenceQueue.NULL. |
79 * |
79 * |
80 * Inactive: queue = ReferenceQueue.NULL; next = this. |
80 * The collector only needs to examine the referent field and the |
81 * |
81 * discovered field to determine whether a (non-FinalReference) Reference |
82 * With this scheme the collector need only examine the next field in order |
82 * object needs special treatment. If the referent is non-null and not |
83 * to determine whether a Reference instance requires special treatment: If |
83 * known to be live, then it may need to be discovered for possible later |
84 * the next field is null then the instance is active; if it is non-null, |
84 * notification. But if the discovered field is non-null, then it has |
85 * then the collector should treat the instance normally. |
85 * already been discovered. |
86 * |
86 * |
87 * To ensure that a concurrent collector can discover active Reference |
87 * FinalReference (which exists to support finalization) differs from |
88 * objects without interfering with application threads that may apply |
88 * other references, because a FinalReference is not cleared when |
89 * the enqueue() method to those objects, collectors should link |
89 * notified. The referent being null or not cannot be used to distinguish |
90 * discovered objects through the discovered field. The discovered |
90 * between the active state and pending or inactive states. However, |
91 * field is also used for linking Reference objects in the pending list. |
91 * FinalReferences do not support enqueue(). Instead, the next field of a |
|
92 * FinalReference object is set to "this" when it is added to the |
|
93 * pending-Reference list. The use of "this" as the value of next in the |
|
94 * enqueued and dequeued states maintains the non-active state. An |
|
95 * additional check that the next field is null is required to determine |
|
96 * that a FinalReference object is active. |
|
97 * |
|
98 * Initial states: |
|
99 * [active/registered] |
|
100 * [active/unregistered] [1] |
|
101 * |
|
102 * Transitions: |
|
103 * clear |
|
104 * [active/registered] -------> [inactive/registered] |
|
105 * | | |
|
106 * | | enqueue [2] |
|
107 * | GC enqueue [2] | |
|
108 * | -----------------| |
|
109 * | | |
|
110 * v | |
|
111 * [pending/registered] --- v |
|
112 * | | ReferenceHandler |
|
113 * | enqueue [2] |---> [inactive/enqueued] |
|
114 * v | | |
|
115 * [pending/enqueued] --- | |
|
116 * | | poll/remove |
|
117 * | poll/remove | |
|
118 * | | |
|
119 * v ReferenceHandler v |
|
120 * [pending/dequeued] ------> [inactive/dequeued] |
|
121 * |
|
122 * |
|
123 * clear/enqueue/GC [3] |
|
124 * [active/unregistered] ------ |
|
125 * | | |
|
126 * | GC | |
|
127 * | |--> [inactive/unregistered] |
|
128 * v | |
|
129 * [pending/unregistered] ------ |
|
130 * ReferenceHandler |
|
131 * |
|
132 * Terminal states: |
|
133 * [inactive/dequeued] |
|
134 * [inactive/unregistered] |
|
135 * |
|
136 * Unreachable states (because enqueue also clears): |
|
137 * [active/enqeued] |
|
138 * [active/dequeued] |
|
139 * |
|
140 * [1] Unregistered is not permitted for FinalReferences. |
|
141 * |
|
142 * [2] These transitions are not possible for FinalReferences, making |
|
143 * [pending/enqueued] and [pending/dequeued] unreachable, and |
|
144 * [inactive/registered] terminal. |
|
145 * |
|
146 * [3] The garbage collector may directly transition a Reference |
|
147 * from [active/unregistered] to [inactive/unregistered], |
|
148 * bypassing the pending-Reference list. |
92 */ |
149 */ |
93 |
150 |
94 private T referent; /* Treated specially by GC */ |
151 private T referent; /* Treated specially by GC */ |
95 |
152 |
|
153 /* The queue this reference gets enqueued to by GC notification or by |
|
154 * calling enqueue(). |
|
155 * |
|
156 * When registered: the queue with which this reference is registered. |
|
157 * enqueued: ReferenceQueue.ENQUEUE |
|
158 * dequeued: ReferenceQueue.NULL |
|
159 * unregistered: ReferenceQueue.NULL |
|
160 */ |
96 volatile ReferenceQueue<? super T> queue; |
161 volatile ReferenceQueue<? super T> queue; |
97 |
162 |
98 /* When active: NULL |
163 /* The link in a ReferenceQueue's list of Reference objects. |
99 * pending: this |
164 * |
100 * Enqueued: next reference in queue (or this if last) |
165 * When registered: null |
101 * Inactive: this |
166 * enqueued: next element in queue (or this if last) |
|
167 * dequeued: this (marking FinalReferences as inactive) |
|
168 * unregistered: null |
102 */ |
169 */ |
103 @SuppressWarnings("rawtypes") |
170 @SuppressWarnings("rawtypes") |
104 volatile Reference next; |
171 volatile Reference next; |
105 |
172 |
106 /* When active: next element in a discovered reference list maintained by GC (or this if last) |
173 /* Used by the garbage collector to accumulate Reference objects that need |
107 * pending: next element in the pending list (or null if last) |
174 * to be revisited in order to decide whether they should be notified. |
108 * otherwise: NULL |
175 * Also used as the link in the pending-Reference list. The discovered |
109 */ |
176 * field and the next field are distinct to allow the enqueue() method to |
110 private transient Reference<T> discovered; /* used by VM */ |
177 * be applied to a Reference object while it is either in the |
|
178 * pending-Reference list or in the garbage collector's discovered set. |
|
179 * |
|
180 * When active: null or next element in a discovered reference list |
|
181 * maintained by the GC (or this if last) |
|
182 * pending: next element in the pending-Reference list (null if last) |
|
183 * inactive: null |
|
184 */ |
|
185 private transient Reference<T> discovered; |
111 |
186 |
112 |
187 |
113 /* High-priority thread to enqueue pending References |
188 /* High-priority thread to enqueue pending References |
114 */ |
189 */ |
115 private static class ReferenceHandler extends Thread { |
190 private static class ReferenceHandler extends Thread { |