1 /*
2 * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.lang.ref;
27
28 import jdk.internal.vm.annotation.AOTSafeClassInitializer;
29 import jdk.internal.vm.annotation.ForceInline;
30 import jdk.internal.vm.annotation.IntrinsicCandidate;
31 import jdk.internal.access.JavaLangRefAccess;
32 import jdk.internal.access.SharedSecrets;
33
34 import java.util.Objects;
35
36 /**
37 * Abstract base class for reference objects. This class defines the
38 * operations common to all reference objects. Because reference objects are
39 * implemented in close cooperation with the garbage collector, this class may
40 * not be subclassed directly.
41 *
42 * <div class="preview-block">
43 * <div class="preview-comment">
44 * The referent must have {@linkplain Objects#hasIdentity(Object) object identity}.
45 * When preview features are enabled, attempts to create a reference
46 * to a {@linkplain Class#isValue value object} result in an {@link IdentityException}.
47 * </div>
48 * </div>
49 * @param <T> the type of the referent
50 *
51 * @author Mark Reinhold
52 * @since 1.2
53 * @sealedGraph
54 */
55 @AOTSafeClassInitializer
56 public abstract sealed class Reference<@jdk.internal.RequiresIdentity T>
57 permits PhantomReference, SoftReference, WeakReference, FinalReference {
58
59 /* The state of a Reference object is characterized by two attributes. It
60 * may be either "active", "pending", or "inactive". It may also be
61 * either "registered", "enqueued", "dequeued", or "unregistered".
62 *
63 * Active: Subject to special treatment by the garbage collector. Some
64 * time after the collector detects that the reachability of the
65 * referent has changed to the appropriate state, the collector
66 * "notifies" the reference, changing the state to either "pending" or
67 * "inactive".
68 * referent != null; discovered = null, or in GC discovered list.
69 *
70 * Pending: An element of the pending-Reference list, waiting to be
71 * processed by the ReferenceHandler thread. The pending-Reference
72 * list is linked through the discovered fields of references in the
73 * list.
74 * referent = null; discovered = next element in pending-Reference list.
75 *
76 * Inactive: Neither Active nor Pending.
77 * referent = null.
78 *
79 * Registered: Associated with a queue when created, and not yet added
80 * to the queue.
81 * queue = the associated queue.
82 *
83 * Enqueued: Added to the associated queue, and not yet removed.
84 * queue = ReferenceQueue.ENQUEUE; next = next entry in list, or this to
85 * indicate end of list.
86 *
87 * Dequeued: Added to the associated queue and then removed.
88 * queue = ReferenceQueue.NULL_QUEUE; next = this.
89 *
90 * Unregistered: Not associated with a queue when created.
91 * queue = ReferenceQueue.NULL_QUEUE.
92 *
93 * The collector only needs to examine the referent field and the
94 * discovered field to determine whether a (non-FinalReference) Reference
95 * object needs special treatment. If the referent is non-null and not
96 * known to be live, then it may need to be discovered for possible later
97 * notification. But if the discovered field is non-null, then it has
98 * already been discovered.
99 *
100 * FinalReference (which exists to support finalization) differs from
101 * other references, because a FinalReference is not cleared when
102 * notified. The referent being null or not cannot be used to distinguish
103 * between the active state and pending or inactive states. However,
104 * FinalReferences do not support enqueue(). Instead, the next field of a
105 * FinalReference object is set to "this" when it is added to the
106 * pending-Reference list. The use of "this" as the value of next in the
107 * enqueued and dequeued states maintains the non-active state. An
108 * additional check that the next field is null is required to determine
109 * that a FinalReference object is active.
110 *
111 * Initial states:
112 * [active/registered]
113 * [active/unregistered] [1]
114 *
115 * Transitions:
116 * clear [2]
117 * [active/registered] -------> [inactive/registered]
118 * | |
119 * | | enqueue
120 * | GC enqueue [2] |
121 * | -----------------|
122 * | |
123 * v |
124 * [pending/registered] --- v
125 * | | ReferenceHandler
126 * | enqueue [2] |---> [inactive/enqueued]
127 * v | |
128 * [pending/enqueued] --- |
129 * | | poll/remove
130 * | poll/remove | + clear [4]
131 * | |
132 * v ReferenceHandler v
133 * [pending/dequeued] ------> [inactive/dequeued]
134 *
135 *
136 * clear/enqueue/GC [3]
137 * [active/unregistered] ------
138 * | |
139 * | GC |
140 * | |--> [inactive/unregistered]
141 * v |
142 * [pending/unregistered] ------
143 * ReferenceHandler
144 *
145 * Terminal states:
146 * [inactive/dequeued]
147 * [inactive/unregistered]
148 *
149 * Unreachable states (because enqueue also clears):
150 * [active/enqueued]
151 * [active/dequeued]
152 *
153 * [1] Unregistered is not permitted for FinalReferences.
154 *
155 * [2] These transitions are not possible for FinalReferences, making
156 * [pending/enqueued], [pending/dequeued], and [inactive/registered]
157 * unreachable.
158 *
159 * [3] The garbage collector may directly transition a Reference
160 * from [active/unregistered] to [inactive/unregistered],
161 * bypassing the pending-Reference list.
162 *
163 * [4] The queue handler for FinalReferences also clears the reference.
164 */
165
166 private T referent; /* Treated specially by GC */
167
168 /* The queue this reference gets enqueued to by GC notification or by
169 * calling enqueue().
170 *
171 * When registered: the queue with which this reference is registered.
172 * enqueued: ReferenceQueue.ENQUEUE
173 * dequeued: ReferenceQueue.NULL_QUEUE
174 * unregistered: ReferenceQueue.NULL_QUEUE
175 */
176 volatile ReferenceQueue<? super T> queue;
177
178 /* The link in a ReferenceQueue's list of Reference objects.
179 *
180 * When registered: null
181 * enqueued: next element in queue (or this if last)
182 * dequeued: this (marking FinalReferences as inactive)
183 * unregistered: null
184 */
185 @SuppressWarnings("rawtypes")
186 volatile Reference next;
187
188 /* Used by the garbage collector to accumulate Reference objects that need
189 * to be revisited in order to decide whether they should be notified.
190 * Also used as the link in the pending-Reference list. The discovered
191 * field and the next field are distinct to allow the enqueue() method to
192 * be applied to a Reference object while it is either in the
193 * pending-Reference list or in the garbage collector's discovered set.
194 *
195 * When active: null or next element in a discovered reference list
196 * maintained by the GC (or this if last)
197 * pending: next element in the pending-Reference list (null if last)
198 * inactive: null
199 */
200 private transient Reference<?> discovered;
201
202
203 /* High-priority thread to enqueue pending References
204 */
205 private static class ReferenceHandler extends Thread {
206 ReferenceHandler(ThreadGroup g, String name) {
207 super(g, null, name, 0, false);
208 }
209
210 public void run() {
211 while (true) {
212 processPendingReferences();
213 }
214 }
215 }
216
217 /*
218 * Atomically get and clear (set to null) the VM's pending-Reference list.
219 */
220 private static native Reference<?> getAndClearReferencePendingList();
221
222 /*
223 * Test whether the VM's pending-Reference list contains any entries.
224 */
225 private static native boolean hasReferencePendingList();
226
227 /*
228 * Wait until the VM's pending-Reference list may be non-null.
229 */
230 private static native void waitForReferencePendingList();
231
232 /*
233 * Enqueue a Reference taken from the pending list. Calling this method
234 * takes us from the Reference<?> domain of the pending list elements to
235 * having a Reference<T> with a correspondingly typed queue.
236 */
237 private void enqueueFromPending() {
238 var q = queue;
239 if (q != ReferenceQueue.NULL_QUEUE) q.enqueue(this);
240 }
241
242 private static final Object processPendingLock = new Object();
243 private static boolean processPendingActive = false;
244
245 private static void processPendingReferences() {
246 // Only the singleton reference processing thread calls
247 // waitForReferencePendingList() and getAndClearReferencePendingList().
248 // These are separate operations to avoid a race with other threads
249 // that are calling waitForReferenceProcessing().
250 waitForReferencePendingList();
251 Reference<?> pendingList;
252 synchronized (processPendingLock) {
253 pendingList = getAndClearReferencePendingList();
254 processPendingActive = true;
255 }
256 while (pendingList != null) {
257 Reference<?> ref = pendingList;
258 pendingList = ref.discovered;
259 ref.discovered = null;
260 ref.enqueueFromPending();
261 }
262 // Notify any waiters of completion of current round.
263 synchronized (processPendingLock) {
264 processPendingActive = false;
265 processPendingLock.notifyAll();
266 }
267 }
268
269 // Wait for progress in reference processing.
270 //
271 // Returns true after waiting (for notification from the reference
272 // processing thread) if either (1) the VM has any pending
273 // references, or (2) the reference processing thread is
274 // processing references. Otherwise, returns false immediately.
275 private static boolean waitForReferenceProcessing()
276 throws InterruptedException
277 {
278 synchronized (processPendingLock) {
279 if (processPendingActive || hasReferencePendingList()) {
280 // Wait for progress, not necessarily completion.
281 processPendingLock.wait();
282 return true;
283 } else {
284 return false;
285 }
286 }
287 }
288
289 /**
290 * Start the Reference Handler thread as a daemon thread.
291 */
292 static void startReferenceHandlerThread(ThreadGroup tg) {
293 Thread handler = new ReferenceHandler(tg, "Reference Handler");
294 /* If there were a special system-only priority greater than
295 * MAX_PRIORITY, it would be used here
296 */
297 handler.setPriority(Thread.MAX_PRIORITY);
298 handler.setDaemon(true);
299 handler.start();
300 }
301
302 static {
303 // provide access in SharedSecrets
304 SharedSecrets.setJavaLangRefAccess(new JavaLangRefAccess() {
305 @Override
306 public void startThreads() {
307 ThreadGroup tg = Thread.currentThread().getThreadGroup();
308 for (ThreadGroup tgn = tg;
309 tgn != null;
310 tg = tgn, tgn = tg.getParent());
311 Reference.startReferenceHandlerThread(tg);
312 Finalizer.startFinalizerThread(tg);
313 }
314
315 @Override
316 public boolean waitForReferenceProcessing()
317 throws InterruptedException
318 {
319 return Reference.waitForReferenceProcessing();
320 }
321
322 @Override
323 public void runFinalization() {
324 Finalizer.runFinalization();
325 }
326 });
327 }
328
329 /* -- Referent accessor and setters -- */
330
331 /**
332 * Returns this reference object's referent. If this reference object has
333 * been cleared, either by the program or by the garbage collector, then
334 * this method returns {@code null}.
335 *
336 * @apiNote
337 * This method returns a strong reference to the referent. This may cause
338 * the garbage collector to treat it as strongly reachable until some later
339 * collection cycle. The {@link #refersTo(Object) refersTo} method can be
340 * used to avoid such strengthening when testing whether some object is
341 * the referent of a reference object; that is, use {@code ref.refersTo(obj)}
342 * rather than {@code ref.get() == obj}.
343 *
344 * @return The object to which this reference refers, or
345 * {@code null} if this reference object has been cleared
346 * @see #refersTo
347 */
348 public T get() {
349 return get0();
350 }
351
352 /* Implementation of get(). This method exists to avoid making get() all
353 * of virtual, native, and intrinsic candidate. That could have the
354 * undesirable effect of having the native method used instead of the
355 * intrinsic when devirtualization fails.
356 */
357 @IntrinsicCandidate
358 private native T get0();
359
360 /**
361 * Tests if the referent of this reference object is {@code obj}.
362 * Using a {@code null} {@code obj} returns {@code true} if the
363 * reference object has been cleared.
364 *
365 * @param obj the object to compare with this reference object's referent
366 * @return {@code true} if {@code obj} is the referent of this reference object
367 * @since 16
368 */
369 public final boolean refersTo(T obj) {
370 return refersToImpl(obj);
371 }
372
373 /* Implementation of refersTo(), overridden for phantom references.
374 * This method exists only to avoid making refersTo0() virtual. Making
375 * refersTo0() virtual has the undesirable effect of C2 often preferring
376 * to call the native implementation over the intrinsic.
377 */
378 boolean refersToImpl(T obj) {
379 return refersTo0(obj);
380 }
381
382 @IntrinsicCandidate
383 private native boolean refersTo0(Object o);
384
385 /**
386 * Clears this reference object. Invoking this method does not enqueue this
387 * object, and the garbage collector will not clear or enqueue this object.
388 *
389 * <p>When the garbage collector or the {@link #enqueue()} method clear
390 * references they do so directly, without invoking this method.
391 *
392 * @apiNote
393 * There is a potential race condition with the garbage collector. When this
394 * method is called, the garbage collector may already be in the process of
395 * (or already completed) clearing and/or enqueueing this reference.
396 * Avoid this race by ensuring the referent remains strongly reachable until
397 * after the call to clear(), using {@link #reachabilityFence(Object)} if
398 * necessary.
399 */
400 public void clear() {
401 clearImpl();
402 }
403
404 /* Implementation of clear(). A simple assignment of the referent field
405 * won't do for some garbage collectors. There is the override for phantom
406 * references, which requires different semantics. This method is also
407 * used by enqueue().
408 *
409 * <p>This method exists only to avoid making clear0() virtual. Making
410 * clear0() virtual has the undesirable effect of C2 often preferring
411 * to call the native implementation over the intrinsic.
412 */
413 void clearImpl() {
414 clear0();
415 }
416
417 @IntrinsicCandidate
418 private native void clear0();
419
420 /* -- Operations on inactive FinalReferences -- */
421
422 /* These functions are only used by FinalReference, and must only be
423 * called after the reference becomes inactive. While active, a
424 * FinalReference is considered weak but the referent is not normally
425 * accessed. Once a FinalReference becomes inactive it is considered a
426 * strong reference. These functions are used to bypass the
427 * corresponding weak implementations, directly accessing the referent
428 * field with strong semantics.
429 */
430
431 /**
432 * Load referent with strong semantics.
433 */
434 T getFromInactiveFinalReference() {
435 assert this instanceof FinalReference;
436 assert next != null; // I.e. FinalReference is inactive
437 return this.referent;
438 }
439
440 /**
441 * Clear referent with strong semantics.
442 */
443 void clearInactiveFinalReference() {
444 assert this instanceof FinalReference;
445 assert next != null; // I.e. FinalReference is inactive
446 this.referent = null;
447 }
448
449 /* -- Queue operations -- */
450
451 /**
452 * Tests if this reference object is in its associated queue, if any.
453 * This method returns {@code true} only if all of the following conditions
454 * are met:
455 * <ul>
456 * <li>this reference object was registered with a queue when it was created; and
457 * <li>the garbage collector has added this reference object to the queue
458 * or {@link #enqueue()} is called; and
459 * <li>this reference object is not yet removed from the queue.
460 * </ul>
461 * Otherwise, this method returns {@code false}.
462 * This method may return {@code false} if this reference object has been cleared
463 * but not enqueued due to the race condition.
464 *
465 * @deprecated
466 * This method was originally specified to test if a reference object has
467 * been cleared and enqueued but was never implemented to do this test.
468 * This method could be misused due to the inherent race condition
469 * or without an associated {@code ReferenceQueue}.
470 * An application relying on this method to release critical resources
471 * could cause serious performance issue.
472 * An application should use {@link ReferenceQueue} to reliably determine
473 * what reference objects that have been enqueued or
474 * {@link #refersTo(Object) refersTo(null)} to determine if this reference
475 * object has been cleared.
476 *
477 * @return {@code true} if and only if this reference object is
478 * in its associated queue (if any).
479 */
480 @Deprecated(since="16")
481 public boolean isEnqueued() {
482 return (this.queue == ReferenceQueue.ENQUEUED);
483 }
484
485 /**
486 * Clears this reference object, then attempts to add it to the queue with
487 * which it is registered, if any.
488 *
489 * <p>If this reference is registered with a queue but not yet enqueued,
490 * the reference is added to the queue; this method is
491 * <b><i>successful</i></b> and returns true.
492 * If this reference is not registered with a queue, or was already enqueued
493 * (by the garbage collector, or a previous call to {@code enqueue}), this
494 * method is <b><i>unsuccessful</i></b> and returns false.
495 *
496 * <p>{@linkplain java.lang.ref##MemoryConsistency Memory consistency effects}:
497 * Actions in a thread prior to a <b><i>successful</i></b> call to {@code enqueue}
498 * <a href="{@docRoot}/java.base/java/util/concurrent/package-summary.html#MemoryVisibility"><i>happen-before</i></a>
499 * the reference is removed from the queue by {@link ReferenceQueue#poll}
500 * or {@link ReferenceQueue#remove}. <b><i>Unsuccessful</i></b> calls to
501 * {@code enqueue} have no specified memory consistency effects.
502 *
503 * <p> When this method clears references it does so directly, without
504 * invoking the {@link #clear()} method. When the garbage collector clears
505 * and enqueues references it does so directly, without invoking the
506 * {@link #clear()} method or this method.
507 *
508 * @apiNote
509 * Use of this method allows the registered queue's
510 * {@link ReferenceQueue#poll} and {@link ReferenceQueue#remove} methods
511 * to return this reference even though the referent may still be strongly
512 * reachable.
513 *
514 * @return {@code true} if this reference object was successfully
515 * enqueued; {@code false} if it was already enqueued or if
516 * it was not registered with a queue when it was created
517 */
518 public boolean enqueue() {
519 clearImpl(); // Intentionally clearImpl() to dispatch to overridden method, if needed
520 return this.queue.enqueue(this);
521 }
522
523 /**
524 * Throws {@link CloneNotSupportedException}. A {@code Reference} cannot be
525 * meaningfully cloned. Construct a new {@code Reference} instead.
526 *
527 * @return never returns normally
528 * @throws CloneNotSupportedException always
529 */
530 @Override
531 protected Object clone() throws CloneNotSupportedException {
532 throw new CloneNotSupportedException();
533 }
534
535 /* -- Constructors -- */
536
537 Reference(T referent) {
538 this(referent, null);
539 }
540
541 Reference(T referent, ReferenceQueue<? super T> queue) {
542 if (referent != null) {
543 Objects.requireIdentity(referent);
544 }
545 this.referent = referent;
546 this.queue = (queue == null) ? ReferenceQueue.NULL_QUEUE : queue;
547 }
548
549 /**
550 * Ensures that the given object remains
551 * <a href="package-summary.html#reachability"><em>strongly reachable</em></a>.
552 * This reachability is assured regardless of any optimizing transformations
553 * the virtual machine may perform that might otherwise allow the object to
554 * become unreachable (see JLS {@jls 12.6.1}). Thus, the given object is not
555 * reclaimable by garbage collection at least until after the invocation of
556 * this method. References to the given object will not be cleared (or
557 * enqueued, if applicable) by the garbage collector until after invocation
558 * of this method.
559 * Invocation of this method does not itself initiate reference processing,
560 * garbage collection, or finalization.
561 *
562 * <p> This method establishes an ordering for <em>strong reachability</em>
563 * with respect to garbage collection. It controls relations that are
564 * otherwise only implicit in a program -- the reachability conditions
565 * triggering garbage collection. This method is applicable only
566 * when reclamation may have visible effects,
567 * such as for objects that use finalizers or {@link Cleaner}, or code that
568 * performs {@linkplain java.lang.ref reference processing}.
569 *
570 * <p>{@linkplain java.lang.ref##MemoryConsistency Memory consistency effects}:
571 * Actions in a thread prior to calling {@code reachabilityFence(x)}
572 * <a href="{@docRoot}/java.base/java/util/concurrent/package-summary.html#MemoryVisibility"><i>happen-before</i></a>
573 * the garbage collector clears any reference to {@code x}.
574 *
575 * @apiNote
576 * Reference processing or finalization can occur after an object becomes
577 * unreachable. An object can become unreachable when the virtual machine
578 * detects that there is no further need for the object (other than for
579 * running a finalizer). In the course of optimization, the virtual machine
580 * can reorder operations of an object's methods such that the object
581 * becomes unneeded earlier than might naively be expected —
582 * including while a method of the object is still running. For instance,
583 * the VM can move the loading of <em>values</em> from the object's fields
584 * to occur earlier. The object itself is then no longer needed and becomes
585 * unreachable, and the method can continue running using the obtained values.
586 * This may have surprising and undesirable effects when using a Cleaner or
587 * finalizer for cleanup: there is a race between the
588 * program thread running the method, and the cleanup thread running the
589 * Cleaner or finalizer. The cleanup thread could free a
590 * resource, followed by the program thread (still running the method)
591 * attempting to access the now-already-freed resource.
592 * Use of {@code reachabilityFence} can prevent this race by ensuring that the
593 * object remains strongly reachable.
594 * <p>
595 * The following is an example in which the bookkeeping associated with a class is
596 * managed through array indices. Here, method {@code action} uses a
597 * {@code reachabilityFence} to ensure that the {@code Resource} object is
598 * not reclaimed before bookkeeping on an associated
599 * {@code ExternalResource} has been performed; specifically, to
600 * ensure that the array slot holding the {@code ExternalResource} is not
601 * nulled out in method {@link Object#finalize}, which may otherwise run
602 * concurrently.
603 *
604 * {@snippet :
605 * class Resource {
606 * private static ExternalResource[] externalResourceArray = ...
607 *
608 * int myIndex;
609 * Resource(...) {
610 * this.myIndex = ...
611 * externalResourceArray[myIndex] = ...;
612 * ...
613 * }
614 * protected void finalize() {
615 * externalResourceArray[this.myIndex] = null;
616 * ...
617 * }
618 * public void action() {
619 * try {
620 * // ...
621 * int i = this.myIndex; // last use of 'this' Resource in action()
622 * Resource.update(externalResourceArray[i]);
623 * } finally {
624 * Reference.reachabilityFence(this);
625 * }
626 * }
627 * private static void update(ExternalResource ext) {
628 * ext.status = ...;
629 * }
630 * }
631 * }
632 *
633 * The invocation of {@code reachabilityFence} is
634 * placed <em>after</em> the call to {@code update}, to ensure that the
635 * array slot is not nulled out by {@link Object#finalize} before the
636 * update, even if the call to {@code action} was the last use of this
637 * object. This might be the case if, for example, a usage in a user program
638 * had the form {@code new Resource().action();} which retains no other
639 * reference to this {@code Resource}.
640 * The {@code reachabilityFence} call is placed in a {@code finally} block to
641 * ensure that it is invoked across all paths in the method. A more complex
642 * method might need further precautions to ensure that
643 * {@code reachabilityFence} is encountered along all code paths.
644 *
645 * <p> Method {@code reachabilityFence} is not required in constructions
646 * that themselves ensure reachability. For example, because objects that
647 * are locked cannot, in general, be reclaimed, it would suffice if all
648 * accesses of the object, in all methods of class {@code Resource}
649 * (including {@code finalize}) were enclosed in {@code synchronized (this)}
650 * blocks. (Further, such blocks must not include infinite loops, or
651 * themselves be unreachable, which fall into the corner case exceptions to
652 * the "in general" disclaimer.) However, method {@code reachabilityFence}
653 * remains a better option in cases where synchronization is not as efficient,
654 * desirable, or possible; for example because it would encounter deadlock.
655 *
656 * @param ref the reference to the object to keep strongly reachable. If
657 * {@code null}, this method has no effect.
658 * @since 9
659 */
660 @ForceInline
661 public static void reachabilityFence(Object ref) {
662 // Does nothing. This method is annotated with @ForceInline to eliminate
663 // most of the overhead that using @DontInline would cause with the
664 // HotSpot JVM, when this fence is used in a wide variety of situations.
665 // HotSpot JVM retains the ref and does not GC it before a call to
666 // this method, because the JIT-compilers do not have GC-only safepoints.
667 }
668 }