PageRenderTime 50ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/src/share/classes/java/lang/ref/Reference.java

https://bitbucket.org/weijun/jdk8-tl-jdk
Java | 245 lines | 70 code | 32 blank | 143 comment | 13 complexity | d3813966ed77187d1022e6d0eabb7445 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause-No-Nuclear-License-2014, LGPL-3.0
  1. /*
  2. * Copyright (c) 1997, 2006, 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. package java.lang.ref;
  26. import sun.misc.Cleaner;
  27. /**
  28. * Abstract base class for reference objects. This class defines the
  29. * operations common to all reference objects. Because reference objects are
  30. * implemented in close cooperation with the garbage collector, this class may
  31. * not be subclassed directly.
  32. *
  33. * @author Mark Reinhold
  34. * @since 1.2
  35. */
  36. public abstract class Reference<T> {
  37. /* A Reference instance is in one of four possible internal states:
  38. *
  39. * Active: Subject to special treatment by the garbage collector. Some
  40. * time after the collector detects that the reachability of the
  41. * referent has changed to the appropriate state, it changes the
  42. * instance's state to either Pending or Inactive, depending upon
  43. * whether or not the instance was registered with a queue when it was
  44. * created. In the former case it also adds the instance to the
  45. * pending-Reference list. Newly-created instances are Active.
  46. *
  47. * Pending: An element of the pending-Reference list, waiting to be
  48. * enqueued by the Reference-handler thread. Unregistered instances
  49. * are never in this state.
  50. *
  51. * Enqueued: An element of the queue with which the instance was
  52. * registered when it was created. When an instance is removed from
  53. * its ReferenceQueue, it is made Inactive. Unregistered instances are
  54. * never in this state.
  55. *
  56. * Inactive: Nothing more to do. Once an instance becomes Inactive its
  57. * state will never change again.
  58. *
  59. * The state is encoded in the queue and next fields as follows:
  60. *
  61. * Active: queue = ReferenceQueue with which instance is registered, or
  62. * ReferenceQueue.NULL if it was not registered with a queue; next =
  63. * null.
  64. *
  65. * Pending: queue = ReferenceQueue with which instance is registered;
  66. * next = this
  67. *
  68. * Enqueued: queue = ReferenceQueue.ENQUEUED; next = Following instance
  69. * in queue, or this if at end of list.
  70. *
  71. * Inactive: queue = ReferenceQueue.NULL; next = this.
  72. *
  73. * With this scheme the collector need only examine the next field in order
  74. * to determine whether a Reference instance requires special treatment: If
  75. * the next field is null then the instance is active; if it is non-null,
  76. * then the collector should treat the instance normally.
  77. *
  78. * To ensure that a concurrent collector can discover active Reference
  79. * objects without interfering with application threads that may apply
  80. * the enqueue() method to those objects, collectors should link
  81. * discovered objects through the discovered field. The discovered
  82. * field is also used for linking Reference objects in the pending list.
  83. */
  84. private T referent; /* Treated specially by GC */
  85. ReferenceQueue<? super T> queue;
  86. /* When active: NULL
  87. * pending: this
  88. * Enqueued: next reference in queue (or this if last)
  89. * Inactive: this
  90. */
  91. Reference next;
  92. /* When active: next element in a discovered reference list maintained by GC (or this if last)
  93. * pending: next element in the pending list (or null if last)
  94. * otherwise: NULL
  95. */
  96. transient private Reference<T> discovered; /* used by VM */
  97. /* Object used to synchronize with the garbage collector. The collector
  98. * must acquire this lock at the beginning of each collection cycle. It is
  99. * therefore critical that any code holding this lock complete as quickly
  100. * as possible, allocate no new objects, and avoid calling user code.
  101. */
  102. static private class Lock { };
  103. private static Lock lock = new Lock();
  104. /* List of References waiting to be enqueued. The collector adds
  105. * References to this list, while the Reference-handler thread removes
  106. * them. This list is protected by the above lock object. The
  107. * list uses the discovered field to link its elements.
  108. */
  109. private static Reference pending = null;
  110. /* High-priority thread to enqueue pending References
  111. */
  112. private static class ReferenceHandler extends Thread {
  113. ReferenceHandler(ThreadGroup g, String name) {
  114. super(g, name);
  115. }
  116. public void run() {
  117. for (;;) {
  118. Reference r;
  119. synchronized (lock) {
  120. if (pending != null) {
  121. r = pending;
  122. pending = r.discovered;
  123. r.discovered = null;
  124. } else {
  125. try {
  126. lock.wait();
  127. } catch (InterruptedException x) { }
  128. continue;
  129. }
  130. }
  131. // Fast path for cleaners
  132. if (r instanceof Cleaner) {
  133. ((Cleaner)r).clean();
  134. continue;
  135. }
  136. ReferenceQueue q = r.queue;
  137. if (q != ReferenceQueue.NULL) q.enqueue(r);
  138. }
  139. }
  140. }
  141. static {
  142. ThreadGroup tg = Thread.currentThread().getThreadGroup();
  143. for (ThreadGroup tgn = tg;
  144. tgn != null;
  145. tg = tgn, tgn = tg.getParent());
  146. Thread handler = new ReferenceHandler(tg, "Reference Handler");
  147. /* If there were a special system-only priority greater than
  148. * MAX_PRIORITY, it would be used here
  149. */
  150. handler.setPriority(Thread.MAX_PRIORITY);
  151. handler.setDaemon(true);
  152. handler.start();
  153. }
  154. /* -- Referent accessor and setters -- */
  155. /**
  156. * Returns this reference object's referent. If this reference object has
  157. * been cleared, either by the program or by the garbage collector, then
  158. * this method returns <code>null</code>.
  159. *
  160. * @return The object to which this reference refers, or
  161. * <code>null</code> if this reference object has been cleared
  162. */
  163. public T get() {
  164. return this.referent;
  165. }
  166. /**
  167. * Clears this reference object. Invoking this method will not cause this
  168. * object to be enqueued.
  169. *
  170. * <p> This method is invoked only by Java code; when the garbage collector
  171. * clears references it does so directly, without invoking this method.
  172. */
  173. public void clear() {
  174. this.referent = null;
  175. }
  176. /* -- Queue operations -- */
  177. /**
  178. * Tells whether or not this reference object has been enqueued, either by
  179. * the program or by the garbage collector. If this reference object was
  180. * not registered with a queue when it was created, then this method will
  181. * always return <code>false</code>.
  182. *
  183. * @return <code>true</code> if and only if this reference object has
  184. * been enqueued
  185. */
  186. public boolean isEnqueued() {
  187. synchronized (this) {
  188. return (this.next != null && this.queue == ReferenceQueue.ENQUEUED);
  189. }
  190. }
  191. /**
  192. * Adds this reference object to the queue with which it is registered,
  193. * if any.
  194. *
  195. * <p> This method is invoked only by Java code; when the garbage collector
  196. * enqueues references it does so directly, without invoking this method.
  197. *
  198. * @return <code>true</code> if this reference object was successfully
  199. * enqueued; <code>false</code> if it was already enqueued or if
  200. * it was not registered with a queue when it was created
  201. */
  202. public boolean enqueue() {
  203. return this.queue.enqueue(this);
  204. }
  205. /* -- Constructors -- */
  206. Reference(T referent) {
  207. this(referent, null);
  208. }
  209. Reference(T referent, ReferenceQueue<? super T> queue) {
  210. this.referent = referent;
  211. this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
  212. }
  213. }