127 // get into trouble later in the run loop if there's
128 // memory shortage while loading/initializing it lazily.
129 ensureClassInitialized(Cleaner.class);
130 }
131
132 ReferenceHandler(ThreadGroup g, String name) {
133 super(g, null, name, 0, false);
134 }
135
136 public void run() {
137 while (true) {
138 processPendingReferences();
139 }
140 }
141 }
142
143 /* Atomically get and clear (set to null) the VM's pending list.
144 */
145 private static native Reference<Object> getAndClearReferencePendingList();
146
147 /* Atomically test whether the VM's pending list contains any
148 * entries. If not, and await is true, then block until the
149 * pending list becomes non-empty. The GC adds references to the
150 * pending list and notifies waiting threads when references are
151 * added. Returns true when the pending list was found to be
152 * non-empty.
153 */
154 private static native boolean checkReferencePendingList(boolean await);
155
156 private static final Object processPendingLock = new Object();
157 private static boolean processPendingActive = false;
158
159 private static void processPendingReferences() {
160 checkReferencePendingList(true);
161 Reference<Object> pendingList;
162 synchronized (processPendingLock) {
163 pendingList = getAndClearReferencePendingList();
164 processPendingActive = true;
165 }
166 while (pendingList != null) {
167 Reference<Object> ref = pendingList;
168 pendingList = ref.discovered;
169 ref.discovered = null;
170
171 if (ref instanceof Cleaner) {
172 ((Cleaner)ref).clean();
173 // Notify any waiters that progress has been made.
174 // This improves latency for nio.Bits waiters, which
175 // are the only important ones.
176 synchronized (processPendingLock) {
177 processPendingLock.notifyAll();
178 }
179 } else {
180 ReferenceQueue<? super Object> q = ref.queue;
182 }
183 }
184 // Notify any waiters of completion of current round.
185 synchronized (processPendingLock) {
186 processPendingActive = false;
187 processPendingLock.notifyAll();
188 }
189 }
190
191 /**
192 * Wait for progress in {@link Reference} processing. If there
193 * aren't any pending {@link Reference}s, return immediately.
194 *
195 * @return {@code true} if there were any pending {@link Reference}s,
196 * {@code false} otherwise.
197 */
198 private static boolean waitForReferenceProcessing()
199 throws InterruptedException
200 {
201 synchronized (processPendingLock) {
202 if (processPendingActive || checkReferencePendingList(false)) {
203 // Wait for progress, not necessarily completion.
204 processPendingLock.wait();
205 return true;
206 } else {
207 return false;
208 }
209 }
210 }
211
212 static {
213 ThreadGroup tg = Thread.currentThread().getThreadGroup();
214 for (ThreadGroup tgn = tg;
215 tgn != null;
216 tg = tgn, tgn = tg.getParent());
217 Thread handler = new ReferenceHandler(tg, "Reference Handler");
218 /* If there were a special system-only priority greater than
219 * MAX_PRIORITY, it would be used here
220 */
221 handler.setPriority(Thread.MAX_PRIORITY);
222 handler.setDaemon(true);
|
127 // get into trouble later in the run loop if there's
128 // memory shortage while loading/initializing it lazily.
129 ensureClassInitialized(Cleaner.class);
130 }
131
132 ReferenceHandler(ThreadGroup g, String name) {
133 super(g, null, name, 0, false);
134 }
135
136 public void run() {
137 while (true) {
138 processPendingReferences();
139 }
140 }
141 }
142
143 /* Atomically get and clear (set to null) the VM's pending list.
144 */
145 private static native Reference<Object> getAndClearReferencePendingList();
146
147 /* Test whether the VM's pending list contains any entries.
148 */
149 private static native boolean hasReferencePendingList();
150
151 /* Wait until the VM's pending list may be non-null.
152 */
153 private static native void waitForReferencePendingList();
154
155 private static final Object processPendingLock = new Object();
156 private static boolean processPendingActive = false;
157
158 private static void processPendingReferences() {
159 waitForReferencePendingList();
160 Reference<Object> pendingList;
161 synchronized (processPendingLock) {
162 pendingList = getAndClearReferencePendingList();
163 processPendingActive = true;
164 }
165 while (pendingList != null) {
166 Reference<Object> ref = pendingList;
167 pendingList = ref.discovered;
168 ref.discovered = null;
169
170 if (ref instanceof Cleaner) {
171 ((Cleaner)ref).clean();
172 // Notify any waiters that progress has been made.
173 // This improves latency for nio.Bits waiters, which
174 // are the only important ones.
175 synchronized (processPendingLock) {
176 processPendingLock.notifyAll();
177 }
178 } else {
179 ReferenceQueue<? super Object> q = ref.queue;
181 }
182 }
183 // Notify any waiters of completion of current round.
184 synchronized (processPendingLock) {
185 processPendingActive = false;
186 processPendingLock.notifyAll();
187 }
188 }
189
190 /**
191 * Wait for progress in {@link Reference} processing. If there
192 * aren't any pending {@link Reference}s, return immediately.
193 *
194 * @return {@code true} if there were any pending {@link Reference}s,
195 * {@code false} otherwise.
196 */
197 private static boolean waitForReferenceProcessing()
198 throws InterruptedException
199 {
200 synchronized (processPendingLock) {
201 if (processPendingActive || hasReferencePendingList()) {
202 // Wait for progress, not necessarily completion.
203 processPendingLock.wait();
204 return true;
205 } else {
206 return false;
207 }
208 }
209 }
210
211 static {
212 ThreadGroup tg = Thread.currentThread().getThreadGroup();
213 for (ThreadGroup tgn = tg;
214 tgn != null;
215 tg = tgn, tgn = tg.getParent());
216 Thread handler = new ReferenceHandler(tg, "Reference Handler");
217 /* If there were a special system-only priority greater than
218 * MAX_PRIORITY, it would be used here
219 */
220 handler.setPriority(Thread.MAX_PRIORITY);
221 handler.setDaemon(true);
|