Package java. Lang. Ref;
Import sun. Misc. Cleaner;
/**
* An abstract class is a superclass of all reference classes. This class cannot be directly integrated and is closely related to garbage collection.
* Used to indicate a weak reference. It can encapsulate a strongly referenced object and obtain the object again using the get () method.
* A thread is started in the static block in this class to round the pending object and enable it to join the queue.
*
* Comment by liqiang
*
* @ Author Mark Reinhold
*
*/
Public abstract class reference {
/* A referenced object has four states:
*
* Active (valid): This object is valid and is specially processed by GC. When the accessibility of this object changes (reference to this object ), it will change to suspended or invalid status
* Its object status queue: The registered referencequeue object (registered Queue), referencequeue. null (no registered Queue)
* Next: NULL
*
* Pending: the element is waiting for the queue. elements that do not have a queue registered cannot be in this status.
* Its object status queue: The registered referencequeue object (registered Queue), referencequeue. null (no registered Queue)
* Next: if the next object in the queue is the last object in the queue, next = This
*
* Enqueued: the element is already in the queue. elements that do not have a registered queue cannot be in this status. When an element is removed from the queue, the element status changes to inactive.
* Its object status is queue: referencequeue. enqueued
* Next: if the next object in the queue is the last object in the queue, next = This
*
* Inactive (invalid): indicates that the reference is unavailable. When an element is in this status, its status cannot be changed.
* Its object status is queue = referencequeue. null;
* Next = This.
*
* GC determines the next state. If next = NULL, the next state is active. Otherwise, special processing is required.
*
*/
// The encapsulated object of this reference object
Private object referent;
// Queue of the referenced object
Referencequeue;
// The next element
Reference next;
// Virtual machine usage
Transient private reference discovered;
// A static internal class indicates a lock
Static private class lock {};
Private Static lock = new lock ();
// Element columns waiting for entering the queue
Private Static reference pending = NULL;
// This thread is started during class loading to queue pending Elements
Private Static class referencehandler extends thread {
Referencehandler (threadgroup g, string name ){
Super (G, name );
}
Public void run (){
For (;;){
Reference R;
// Lock is a static object and the thread is started in the static block.
// This refence class has only one thread and lock. The lock aims to protect the data in the synchronization zone block of this object.
Synchronized (LOCK ){
If (pending! = NULL ){
// Retrieve this object if pending is not null
R = pending;
Reference Rn = R. Next;
// Assign the next element of the original pending to the current pending
// If the next element of the original pending is itself, the current pending = NULL
Pending = (Rn = r )? Null: rn;
R. Next = R;
} Else {
Try {
// If no pending object exists, the thread is blocked.
Lock. Wait ();
} Catch (interruptedexception X ){}
Continue;
}
}
// Fast path for cleaners
If (r instanceof cleaner ){
(Cleaner) R). Clean ();
Continue;
}
Referencequeue q = R. Queue;
// Enter the queue if the current element has been registered to the queue
If (Q! = Referencequeue. null) Q. enqueue (R );
}
}
}
Static {
// Obtain the current thread group
Threadgroup Tg = thread. currentthread (). getthreadgroup ();
// Obtain the upper-level system thread group
For (threadgroup tgn = Tg;
Tgn! = NULL;
Tg = tgn, tgn = Tg. getparent ());
// Generate a thread object
Thread handler = new referencehandler (TG, "reference handler ");
// Start the thread
Handler. setpriority (thread. max_priority );
Handler. setdaemon (true );
Handler. Start ();
}
/* -- Referent accessor and setters --*/
/**
*
* Return the strongly referenced object encapsulated by this application object. If the strongly referenced object is reclaimed, or the program calls the clear method of this object
* The returned object is null.
*
* @ Return the object to which this reference refers, or
* <Code> null </code> if this reference object has been cleared
*/
Public object get (){
Return this. referent;
}
/**
*
* Clears its referent object. This method does not team the object.
*/
Public void clear (){
This. referent = NULL;
}
/* -- Queue operations --*/
/**
*
* Determining whether the object is in the queue is to determine whether its internal status is pending or enqueued
*
* @ Return <code> true </code> 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.
*
* Queue operations
*
* @ Return Ture: indicates that the queue is successfully established. False: indicates that the queue has been established or has not been registered.
* @ Return <code> true </code> if this reference object was successfully
* Enqueued; <code> false </code> 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 --*/
// Constructor
Reference (Object referent ){
This (referent, null );
}
// Constructor
Reference (Object referent, referencequeue Queue ){
This. referent = referent;
If (referent = NULL ){
// If the strongly referenced object is null, it indicates that the referenced object is inactive.
/* Immediately make this instance inactive */
This. Queue = referencequeue. null;
This. Next = this;
} Else {
// The initial queue object. If it is not null, it is directly assigned a value. If it is null, it is assigned to referencequeue. null.
This. Queue = (queue = NULL )? Referencequeue. null: queue;
// Next = NULL indicates the active state
This. Next = NULL;
}
}
}