image.png

一、Reference——强、软、若、虚、终结器引用的共同父类

  1. public abstract class Reference<T> {
  2. private T referent; /* Treated specially by GC */
  3. volatile ReferenceQueue<? super T> queue;
  4. @SuppressWarnings("rawtypes")
  5. volatile Reference next;
  6. private transient Reference<?> discovered;
  7. private static class ReferenceHandler extends Thread {
  8. private static void ensureClassInitialized(Class<?> clazz) {
  9. try {
  10. Class.forName(clazz.getName(), true, clazz.getClassLoader());
  11. } catch (ClassNotFoundException e) {
  12. throw (Error) new NoClassDefFoundError(e.getMessage()).initCause(e);
  13. }
  14. }
  15. static {
  16. ensureClassInitialized(Cleaner.class);
  17. }
  18. ReferenceHandler(ThreadGroup g, String name) {
  19. super(g, null, name, 0, false);
  20. }
  21. public void run() {
  22. while (true) {
  23. processPendingReferences();
  24. }
  25. }
  26. }
  27. /*
  28. * Atomically get and clear (set to null) the VM's pending-Reference list.
  29. */
  30. private static native Reference<?> getAndClearReferencePendingList();
  31. /*
  32. * Test whether the VM's pending-Reference list contains any entries.
  33. */
  34. private static native boolean hasReferencePendingList();
  35. /*
  36. * Wait until the VM's pending-Reference list may be non-null.
  37. */
  38. private static native void waitForReferencePendingList();
  39. /*
  40. * Enqueue a Reference taken from the pending list. Calling this method
  41. * takes us from the Reference<?> domain of the pending list elements to
  42. * having a Reference<T> with a correspondingly typed queue.
  43. */
  44. private void enqueueFromPending() {
  45. var q = queue;
  46. if (q != ReferenceQueue.NULL) q.enqueue(this);
  47. }
  48. private static final Object processPendingLock = new Object();
  49. private static boolean processPendingActive = false;
  50. private static void processPendingReferences() {
  51. // Only the singleton reference processing thread calls
  52. // waitForReferencePendingList() and getAndClearReferencePendingList().
  53. // These are separate operations to avoid a race with other threads
  54. // that are calling waitForReferenceProcessing().
  55. waitForReferencePendingList();
  56. Reference<?> pendingList;
  57. synchronized (processPendingLock) {
  58. pendingList = getAndClearReferencePendingList();
  59. processPendingActive = true;
  60. }
  61. while (pendingList != null) {
  62. Reference<?> ref = pendingList;
  63. pendingList = ref.discovered;
  64. ref.discovered = null;
  65. if (ref instanceof Cleaner) {
  66. ((Cleaner)ref).clean();
  67. // Notify any waiters that progress has been made.
  68. // This improves latency for nio.Bits waiters, which
  69. // are the only important ones.
  70. synchronized (processPendingLock) {
  71. processPendingLock.notifyAll();
  72. }
  73. } else {
  74. ref.enqueueFromPending();
  75. }
  76. }
  77. // Notify any waiters of completion of current round.
  78. synchronized (processPendingLock) {
  79. processPendingActive = false;
  80. processPendingLock.notifyAll();
  81. }
  82. }
  83. // Wait for progress in reference processing.
  84. //
  85. // Returns true after waiting (for notification from the reference
  86. // processing thread) if either (1) the VM has any pending
  87. // references, or (2) the reference processing thread is
  88. // processing references. Otherwise, returns false immediately.
  89. private static boolean waitForReferenceProcessing()
  90. throws InterruptedException
  91. {
  92. synchronized (processPendingLock) {
  93. if (processPendingActive || hasReferencePendingList()) {
  94. // Wait for progress, not necessarily completion.
  95. processPendingLock.wait();
  96. return true;
  97. } else {
  98. return false;
  99. }
  100. }
  101. }
  102. static {
  103. ThreadGroup tg = Thread.currentThread().getThreadGroup();
  104. for (ThreadGroup tgn = tg;
  105. tgn != null;
  106. tg = tgn, tgn = tg.getParent());
  107. Thread handler = new ReferenceHandler(tg, "Reference Handler");
  108. /* If there were a special system-only priority greater than
  109. * MAX_PRIORITY, it would be used here
  110. */
  111. handler.setPriority(Thread.MAX_PRIORITY);
  112. handler.setDaemon(true);
  113. handler.start();
  114. // provide access in SharedSecrets
  115. SharedSecrets.setJavaLangRefAccess(new JavaLangRefAccess() {
  116. @Override
  117. public boolean waitForReferenceProcessing()
  118. throws InterruptedException
  119. {
  120. return Reference.waitForReferenceProcessing();
  121. }
  122. @Override
  123. public void runFinalization() {
  124. Finalizer.runFinalization();
  125. }
  126. });
  127. }
  128. /* -- Referent accessor and setters -- */
  129. /**
  130. * Returns this reference object's referent. If this reference object has
  131. * been cleared, either by the program or by the garbage collector, then
  132. * this method returns {@code null}.
  133. *
  134. * @apiNote
  135. * This method returns a strong reference to the referent. This may cause
  136. * the garbage collector to treat it as strongly reachable until some later
  137. * collection cycle. The {@link #refersTo(Object) refersTo} method can be
  138. * used to avoid such strengthening when testing whether some object is
  139. * the referent of a reference object; that is, use {@code ref.refersTo(obj)}
  140. * rather than {@code ref.get() == obj}.
  141. *
  142. * @return The object to which this reference refers, or
  143. * {@code null} if this reference object has been cleared
  144. * @see #refersTo
  145. */
  146. @IntrinsicCandidate
  147. public T get() {
  148. return this.referent;
  149. }
  150. /**
  151. * Tests if the referent of this reference object is {@code obj}.
  152. * Using a {@code null} {@code obj} returns {@code true} if the
  153. * reference object has been cleared.
  154. *
  155. * @param obj the object to compare with this reference object's referent
  156. * @return {@code true} if {@code obj} is the referent of this reference object
  157. * @since 16
  158. */
  159. public final boolean refersTo(T obj) {
  160. return refersToImpl(obj);
  161. }
  162. /* Implementation of refersTo(), overridden for phantom references.
  163. * This method exists only to avoid making refersTo0() virtual. Making
  164. * refersTo0() virtual has the undesirable effect of C2 often preferring
  165. * to call the native implementation over the intrinsic.
  166. */
  167. boolean refersToImpl(T obj) {
  168. return refersTo0(obj);
  169. }
  170. @IntrinsicCandidate
  171. private native boolean refersTo0(Object o);
  172. /**
  173. * Clears this reference object. Invoking this method will not cause this
  174. * object to be enqueued.
  175. *
  176. * <p> This method is invoked only by Java code; when the garbage collector
  177. * clears references it does so directly, without invoking this method.
  178. */
  179. public void clear() {
  180. clear0();
  181. }
  182. private native void clear0();
  183. /* -- Operations on inactive FinalReferences -- */
  184. /* These functions are only used by FinalReference, and must only be
  185. * called after the reference becomes inactive. While active, a
  186. * FinalReference is considered weak but the referent is not normally
  187. * accessed. Once a FinalReference becomes inactive it is considered a
  188. * strong reference. These functions are used to bypass the
  189. * corresponding weak implementations, directly accessing the referent
  190. * field with strong semantics.
  191. */
  192. /**
  193. * Load referent with strong semantics.
  194. */
  195. T getFromInactiveFinalReference() {
  196. assert this instanceof FinalReference;
  197. assert next != null; // I.e. FinalReference is inactive
  198. return this.referent;
  199. }
  200. /**
  201. * Clear referent with strong semantics.
  202. */
  203. void clearInactiveFinalReference() {
  204. assert this instanceof FinalReference;
  205. assert next != null; // I.e. FinalReference is inactive
  206. this.referent = null;
  207. }
  208. /* -- Queue operations -- */
  209. /**
  210. * Tests if this reference object is in its associated queue, if any.
  211. * This method returns {@code true} only if all of the following conditions
  212. * are met:
  213. * <ul>
  214. * <li>this reference object was registered with a queue when it was created; and
  215. * <li>the garbage collector has added this reference object to the queue
  216. * or {@link #enqueue()} is called; and
  217. * <li>this reference object is not yet removed from the queue.
  218. * </ul>
  219. * Otherwise, this method returns {@code false}.
  220. * This method may return {@code false} if this reference object has been cleared
  221. * but not enqueued due to the race condition.
  222. *
  223. * @deprecated
  224. * This method was originally specified to test if a reference object has
  225. * been cleared and enqueued but was never implemented to do this test.
  226. * This method could be misused due to the inherent race condition
  227. * or without an associated {@code ReferenceQueue}.
  228. * An application relying on this method to release critical resources
  229. * could cause serious performance issue.
  230. * An application should use {@link ReferenceQueue} to reliably determine
  231. * what reference objects that have been enqueued or
  232. * {@link #refersTo(Object) refersTo(null)} to determine if this reference
  233. * object has been cleared.
  234. *
  235. * @return {@code true} if and only if this reference object is
  236. * in its associated queue (if any).
  237. */
  238. @Deprecated(since="16")
  239. public boolean isEnqueued() {
  240. return (this.queue == ReferenceQueue.ENQUEUED);
  241. }
  242. /**
  243. * Clears this reference object and adds it to the queue with which
  244. * it is registered, if any.
  245. *
  246. * <p> This method is invoked only by Java code; when the garbage collector
  247. * enqueues references it does so directly, without invoking this method.
  248. *
  249. * @return {@code true} if this reference object was successfully
  250. * enqueued; {@code false} if it was already enqueued or if
  251. * it was not registered with a queue when it was created
  252. */
  253. public boolean enqueue() {
  254. clear0(); // Intentionally clear0() rather than clear()
  255. return this.queue.enqueue(this);
  256. }
  257. @Override
  258. protected Object clone() throws CloneNotSupportedException {
  259. throw new CloneNotSupportedException();
  260. }
  261. /* -- Constructors -- */
  262. Reference(T referent) {
  263. this(referent, null);
  264. }
  265. Reference(T referent, ReferenceQueue<? super T> queue) {
  266. this.referent = referent;
  267. this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
  268. }
  269. @ForceInline
  270. public static void reachabilityFence(Object ref) {
  271. }
  272. }