java.lang.ref.Reference Maven / Gradle / Ivy
/*
* Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.lang.ref;
/**
* Abstract base class for reference objects. This class defines the
* operations common to all reference objects. Because reference objects are
* implemented in close cooperation with the garbage collector, this class may
* not be subclassed directly.
*
* @author Mark Reinhold
* @since 1.2
*/
public abstract class Reference {
/* A Reference instance is in one of four possible internal states:
*
* Active: Subject to special treatment by the garbage collector. Some
* time after the collector detects that the reachability of the
* referent has changed to the appropriate state, it changes the
* instance's state to either Pending or Inactive, depending upon
* whether or not the instance was registered with a queue when it was
* created. In the former case it also adds the instance to the
* pending-Reference list. Newly-created instances are Active.
*
* Pending: An element of the pending-Reference list, waiting to be
* enqueued by the Reference-handler thread. Unregistered instances
* are never in this state.
*
* Enqueued: An element of the queue with which the instance was
* registered when it was created. When an instance is removed from
* its ReferenceQueue, it is made Inactive. Unregistered instances are
* never in this state.
*
* Inactive: Nothing more to do. Once an instance becomes Inactive its
* state will never change again.
*
* The state is encoded in the queue and next fields as follows:
*
* Active: queue = ReferenceQueue with which instance is registered, or
* ReferenceQueue.NULL if it was not registered with a queue; next =
* null.
*
* Pending: queue = ReferenceQueue with which instance is registered;
* next = Following instance in queue, or this if at end of list.
*
* Enqueued: queue = ReferenceQueue.ENQUEUED; next = Following instance
* in queue, or this if at end of list.
*
* Inactive: queue = ReferenceQueue.NULL; next = this.
*
* With this scheme the collector need only examine the next field in order
* to determine whether a Reference instance requires special treatment: If
* the next field is null then the instance is active; if it is non-null,
* then the collector should treat the instance normally.
*
* To ensure that concurrent collector can discover active Reference
* objects without interfering with application threads that may apply
* the enqueue() method to those objects, collectors should link
* discovered objects through the discovered field.
*/
private T referent; /* Treated specially by GC */
ReferenceQueue super T> queue;
Reference next;
transient private Reference discovered; /* used by VM */
/* 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;
/* -- Referent accessor and setters -- */
/**
* Returns this reference object's referent. If this reference object has
* been cleared, either by the program or by the garbage collector, then
* this method returns null
.
*
* @return The object to which this reference refers, or
* null
if this reference object has been cleared
*/
public T get() {
return this.referent;
}
/**
* Clears this reference object. Invoking this method will not cause this
* object to be enqueued.
*
* This method is invoked only by Java code; when the garbage collector
* clears references it does so directly, without invoking this method.
*/
public void clear() {
this.referent = null;
}
/* -- Queue operations -- */
/**
* Tells whether or not this reference object has been enqueued, either by
* the program or by the garbage collector. If this reference object was
* not registered with a queue when it was created, then this method will
* always return false
.
*
* @return true
if and only if this reference object has
* been enqueued
*/
public boolean isEnqueued() {
/* In terms of the internal states, this predicate actually tests
whether the instance is either Pending or Enqueued */
synchronized (this) {
return (this.queue != ReferenceQueue.NULL) && (this.next != null);
}
}
/**
* Adds this reference object to the queue with which it is registered,
* if any.
*
*
This method is invoked only by Java code; when the garbage collector
* enqueues references it does so directly, without invoking this method.
*
* @return true
if this reference object was successfully
* enqueued; false
if it was already enqueued or if
* it was not registered with a queue when it was created
*/
public boolean enqueue() {
return this.queue.enqueue(this);
}
/* -- Constructors -- */
Reference(T referent) {
this(referent, null);
}
Reference(T referent, ReferenceQueue super T> queue) {
this.referent = referent;
this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
}
}