home *** CD-ROM | disk | FTP | other *** search
Java Source | 1998-03-20 | 10.0 KB | 269 lines |
- /*
- * @(#)Reference.java 1.17 98/03/18
- *
- * Copyright 1997, 1998 by Sun Microsystems, Inc.,
- * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
- * All rights reserved.
- *
- * This software is the confidential and proprietary information
- * of Sun Microsystems, Inc. ("Confidential Information"). You
- * shall not disclose such Confidential Information and shall use
- * it only in accordance with the terms of the license agreement
- * you entered into with Sun.
- */
-
- package java.lang.ref;
-
-
- /**
- * The <code>Reference</code> class contains the core abstractions for
- * <em>reference objects</em>. Reference objects reify references in much the
- * same way that Class objects reify Java classes. That is, a reference object
- * encapsulates a reference to some other object so that the reference itself
- * may be examined and manipulated like any other object.
- *
- * <p> The methods defined in this class allow a program to be notified some
- * time after the collector detects a change in the <em>reachability</em> of a
- * given object. They also allow a program to maintain a reference to an
- * object that does not prevent the object from being considered for
- * reclamation by the garbage collector.
- *
- * <p> Three types of reference objects are supported, each weaker than the
- * last: <em>guarded</em>, <em>weak</em>, and <em>phantom</em>. Each type
- * corresponds to a different level of reachability, as defined below. Guarded
- * references are for implementing sophisticated caches, weak references are
- * for implementing simple caches as well as mappings that do not prevent their
- * keys (or values) from being reclaimed, and phantom references are for
- * scheduling pre-mortem cleanup actions in a more flexible way than is
- * possible with the Java finalization mechanism.
- *
- * <p> Each reference-object type is implemented by subclass of the
- * <code>Reference</code> class. An instance of one of these subclasses
- * encapsulates a single reference to a particular object, called the
- * <em>referent</em>. Each subclass provides methods for getting, setting, and
- * clearing the reference. A program may further subclass these subclasses,
- * adding whatever fields and methods are required for its purposes, or it may
- * use these subclasses without change.
- *
- * <h4>Notification</h4>
- *
- * A program may request to be notified of changes in an object's reachability
- * by <em>registering</em> an appropriate reference object with a <em>reference
- * queue</em> at the time the reference object is created. Some time after the
- * garbage collector determines that the reachability of the referent has
- * changed to the value corresponding to the type of the reference, it will add
- * the reference to the associated queue. At this point, the reference is
- * considered to be <em>enqueued</em>. The program may remove references from
- * a queue either by polling or by blocking until a reference becomes
- * available. Reference queues are implemented by the
- * <code>ReferenceQueue</code> class.
- *
- * <p> The relationship between a registered reference object and its queue is
- * one-sided. That is, a queue does not keep track of the references that are
- * registered with it. If a registered reference becomes unreachable itself,
- * then it will never be enqueued. It is the responsibility of the program
- * using reference objects to ensure that the objects remain reachable for as
- * long as the program is interested in their referents.
- *
- * <p> While some programs will choose to dedicate a thread to removing
- * reference objects from one or more queues and processing them, this is by no
- * means necessary. A tactic that often works well is to examine a reference
- * queue in the course of performing some other fairly-frequent action. For
- * example, a hashtable that uses weak references to implement weak keys could
- * poll its reference queue each time the table is accessed. Because the
- * <code>poll</code> method simply checks an internal data structure, this
- * check will add little overhead to the hashtable access methods.
- *
- * <h4>Weak references</h4>
- *
- * A weak reference is automatically cleared by the collector at the same time
- * it is added to the queue with which it is registered, if any. If there is
- * more than one weak reference to an object, all such references will be
- * cleared (and enqueued, if need be) simultaneously and atomically from the
- * standpoint of the program. Thus weak references need not be registered with
- * a queue in order to be useful, while guarded and phantom references do.
- * Similarly, an object that is reachable via guarded (or phantom) references
- * will remain so until all such references are cleared, are modified to refer
- * to some other object, or themselves become unreachable.
- *
- * <h4>Reachability</h4>
- *
- * Going from strongest to weakest, the different levels of reachability reflect
- * the life cycle of an object. They are operationally defined as follows:
- *
- * <ul>
- *
- * <li> An object is <em>strongly reachable</em> if it can be reached by some
- * thread without traversing any reference objects. A newly-created object is
- * strongly reachable by the thread that created it.
- *
- * <li> An object is <em>guardedly reachable</em> if it is not strongly
- * reachable but can be reached by traversing a guarded reference.
- *
- * <li> An object is <em>weakly reachable</em> if it is not guardedly reachable
- * but can be reached by traversing a weak reference. When the weak references
- * to a weakly-reachable object are cleared, the object becomes eligible for
- * finalization.
- *
- * <li> Finally, an object is <em>phantom reachable</em> if it is not weakly
- * reachable, it has been finalized, and some phantom reference refers to it.
- * An object becomes <em>unreachable</em>, and eligible for reclamation, when
- * the last phantom reference to it is cleared or becomes unreachable itself.
- *
- * </ul>
- *
- * <p> The <code>SoftReference</code> class defines a fifth type of reference
- * object that is cleared only when the runtime system detects that memory is
- * running low.
- *
- * @version 1.17, 98/03/18
- * @author Mark Reinhold
- * @since JDK1.2
- * @see java.lang.Runtime.MemoryAdvice
- * @see java.lang.ref.ReferenceQueue
- * @see java.lang.ref.GuardedReference
- * @see java.lang.ref.WeakReference
- * @see java.lang.ref.PhantomReference
- * @see java.lang.ref.SoftReference
- */
-
- public abstract class Reference {
-
- private Object referent; /* Treated specially by GC */
- ReferenceQueue queue = null;
- Reference nextPending = null; /* For pending-Reference list */
-
-
- /* A Reference is in one of the following three internal states.
- References in the IDLE and ENQUEUED states are treated as normal objects
- by the collector. The referent field of a Reference in the ACTIVE state
- is treated specially by the collector according to the type of the
- Reference. When the collector detects that the reachability of the
- referent has changed appropriately, it changes the state to ENQUEUED and
- adds the Reference to the pending-Reference list. */
-
- static final int IDLE = 0;
- static final int ACTIVE = 1;
- static final int ENQUEUED = 2;
-
- int state = IDLE;
-
-
- /* Object used to synchronize with the garbage collector. The collector
- must acquire this lock at the beginning of each collection cycle. It is
- therefore critical that any code holding this lock complete as quickly
- as possible, allocate no new objects, and avoid calling user code. */
-
- static private class Lock { };
- private static Lock lock = new Lock();
-
-
- /* List of References waiting to be enqueued. The collector adds
- References to this list, while the Reference-handler thread removes
- them. This list is protected by the above lock object. */
-
- private static Reference pending = null;
-
-
- /* High-priority thread to enqueue pending References */
- private static Thread handler = new ReferenceHandler();
-
- private static class ReferenceHandler extends Thread {
-
- public void run() {
- for (;;) {
-
- Reference r;
- synchronized (lock) {
- if (pending != null) {
- r = pending;
- pending = r.nextPending;
- r.nextPending = null;
- } else {
- try {
- lock.wait();
- } catch (InterruptedException x) { }
- continue;
- }
- }
-
- ReferenceQueue q = r.queue;
- if (q != null) {
- q.enqueue(r);
- } else {
- if (r instanceof WeakReference)
- r.state = ACTIVE;
- else
- r.state = IDLE;
- }
-
- }
- }
- }
-
- static {
- handler.setName("Reference handler");
- /* If there were a special system-only priority greater than
- MAX_PRIORITY, it would be used here */
- handler.setPriority(Thread.MAX_PRIORITY);
- handler.setDaemon(true);
- handler.start();
- }
-
-
- /* -- Referent accessor and setters -- */
-
- /**
- * Return the object to which this reference object refers. If this
- * reference has been cleared, either by the program or by the garbage
- * collector, then return <code>null</code>.
- */
- public Object get() {
- return this.referent;
- }
-
- /**
- * Clear this reference object.
- */
- public void clear() {
- this.referent = null;
- }
-
-
- /* -- Queue operations -- */
-
- /**
- * Tell whether or not this reference object has been enqueued. If this
- * reference object was not registered with a queue when it was created,
- * then this method will always return <code>false</code>.
- */
- public boolean isEnqueued() {
- return (this.state == ENQUEUED);
- }
-
- /**
- * Add this reference to the queue with which it was registered. Return
- * <code>true</code> if this was done successfully; return
- * <code>false</code> if the reference had already been enqueued, or if it
- * had never been registered with a queue.
- */
- public boolean enqueue() {
- ReferenceQueue q = this.queue;
- if (q == null) return false;
- return q.enqueue(this);
- }
-
-
- /* -- Constructors -- */
-
- protected Reference(Object referent) {
- this.referent = referent;
- }
-
- protected Reference(Object referent, ReferenceQueue queue) {
- this(referent);
- this.queue = queue;
- }
-
- }
-