Detailed implementation of reference in Java and the corresponding execution process _java

Source: Internet
Author: User
Tags google guava

First, reference type (except strong reference)

A direct subclass of reference can be understood to be customized by the JVM, so it has no effect in the code to inherit directly from the reference type. Only subclasses that inherit from it, and the corresponding subclass types include the following. (ignoring those that are not used in Java, such as Jnireference)

SoftReference

WeakReference

finalreference

phantomreference

The reference type above is also mentioned in the corresponding Javadoc. Finalreference is specifically designed for finalize methods, and several others have specific application scenarios. Where SoftReference is used in memory-related caching, WeakReference is used in most scenarios related to recycling. Phantomreference is used in the recall scenario with the wrapper object (such as resource leak detection).

You can view several types of subclass information directly in the IDE to see what scenarios are used in most frameworks by inheriting the corresponding types, so that we actually do the selection process.

Second, the reference constructor function

It provides 2 constructors internally, one with a queue and one without a queue. The meaning of the queue is that we can monitor the queue externally. That is, if an object is about to be reclaimed, Then the corresponding reference object will be placed in this queue. We get reference, we can do some more business.

And if you don't, you just keep rotation the reference object, by judging if the inside get returns Null (the Phantomreference object cannot do that, and its get always returns NULL, so it only has a constructor with a queue). Both methods have a corresponding use scenario, depending on the actual application. If you choose to query the queue data in Weakhashmap, determine if there are any objects that will be reclaimed. Instead of Threadlocalmap, you use a decision to determine whether get () is null for processing.

The corresponding constructor looks like this:

Reference (T referent) {This
 (referent, null);
}
 
Reference (T referent, referencequeue< Super t> queue) {
 this.referent = referent;
 This.queue = (queue = null)? ReferenceQueue.NULL:queue;
}

This is a null queue, which can be understood as a queue that does not require any processing of the data in its queues. And it does not have access to any data within it.

In the above object, referent represents the object that it refers to, that is, the object that we need to be wrapped in when we construct it. The definition of the object being reclaimed is that the object has no other references except for the reference reference (not really not being referenced, but gcroot accessibility, To avoid the problem of circular references).

A queue is one that is notified when an object is reclaimed, and when the object is reclaimed, the entire reference object (rather than the object being reclaimed) is placed in the queue, and the external program can then monitor the queue to get the corresponding data.

Third, referencequeue and reference reference chain

The queues here are nominally a queue, but the actual internal is not a real storage structure, its storage is dependent on the relationship between the internal nodes to express. It can be understood that a queue is a structure similar to a linked list, The node here is actually the reference itself. It can be understood that a queue is a container for a list, and that it stores only the current head node, and that the following nodes are persisted by each reference node itself through next.

Reference State Value

Each reference object has a corresponding state description, that is, describing itself and the packaging object is currently in a state of what, to facilitate the query, positioning or processing.

1, Active: Active state, that is, the corresponding object is a strong reference state, has not been recycled, this state of the object will not be placed in the queue. In this state, next is the queue that is referenced when null,queue is defined.

2, Pending: Ready to put in the queue, in this state to deal with the object will be queued to the queue. In this time window period, the corresponding object is the Pending state. No matter what the reference, enter into this state, can be considered corresponding to this state, Next for yourself (set by the JVM), the queue is referenced by the queue as defined.

3, enqueued: The corresponding object has been for recycling, and the corresponding reference object has been placed in the queue. Prepare to be consulted by the external thread to obtain the appropriate data. In this state, next is the next object to be processed, and the queue is a special identity object enqueued.

4, Inactive: This object has been obtained from the outside of the queue, and has been disposed of. That means that this reference object can be reclaimed, and that the internally encapsulated object can also be reclaimed (the actual recycle operation depends on whether the clear action is invoked). It can be understood that the certainty of entry into this state should be recycled.

The JVM does not need to define a state value to determine which state the referenced state is in, only by calculating the next and the queue.

Four, Referencequeue#head

Always save the most recent node in the current queue to be processed, and you can consider the queue as a LIFO queue. When the new node enters, take the following logic

Newe.next = Head;head=newe;

Then, at the time of acquisition, take the corresponding logic

TMP = Head;head=tmp.next;return tmp;

Five, Reference#next

That is, the next node to be processed that is stored by the current reference node is described. But next only makes sense in the queue. To describe the corresponding state value, The queue will no longer be referenced. Instead, it refers to a special enqueued. Because it has been placed in the queue and will not be placed in the queue again.

VI. reference#referent

That describes the actual object referenced by the current reference. As described in the note, it is handled carefully. That is, when this is reclaimed, and if it is reclaimed, it is directly null, and the external program can learn by referencing the object itself (not referent) about the generation of the recycle behavior.

Vii. Referencequeue#enqueue Pending reference

This process is the process of reference objects from active->pending->enqued. This method is the enqued state for the object that handles the pending state. The corresponding process is the previous logic, the next node to join the operation, the corresponding code as shown below.

R.queue = enqueued;
R.next = (head = = null)? R:head;
Head = R;
queuelength++;
Lock.notifyall ();

The final nitify is to notify the external program of blocking the current queue. (That is, you haven't got the object to be processed before)

Eight, reference#tryhandlepending

That is, to handle changes in the reference object from active to pending state. Inside the Reference object, there is a static field with the corresponding declaration as follows:

/* List of References waiting to be enqueued. The collector adds
 * References to this list while the Reference-handler thread removes
 * them. This list was protected by the above lock object. The
 * List uses the discovered field to link its elements.
 *
private static reference<object> pending = NULL;

It is understandable that the JVM will be dealing with the object in the GC when it is placed above this static field. Also, another field, discovered, represents the next object for the object to be processed. That is, it is understandable that the object to be processed is also a linked list, queued through discovered, This side just need to keep getting pending, and then through the discovered constantly get the next object can be. Because this pending object, two threads can access, so need to lock processing.

The corresponding processing process is as follows:

if (pending!= null) {
 r = pending;
 ' instanceof ' might throw outofmemoryerror sometimes
 //So does this before un-linking ' R ' to ' pending ' chain. .
 c = r instanceof Cleaner? (Cleaner) R:null;
 Unlink ' R ' from ' pending ' chain
 pending = r.discovered;
 r.discovered = null;
} 
The Process object will enter into the enqued state
referencequeue< Super object> q = r.queue;
if (q!= referencequeue.null) Q.enqueue (R);

Nine, Reference#clear

Clears the original object referenced by the referenced object. This way you can no longer access the original object by using the Get () method. From the corresponding design ideas, since all into the queue object, it means that the corresponding object needs to be recycled, because there is no need to access the original object. This method is not invoked by the JVM, Instead, the JVM clears the reference directly from the field operation, and its implementation is consistent with the current method.

The semantics of clear is to place the referent null.

After the WeakReference object enters the queue, the corresponding referent is null.

SoftReference object, the natural corresponding reference will not be null if the object is in sufficient memory to enter the queue. If required to be processed (insufficient memory or other policy), the corresponding referent is null and then entered into the queue.

Finalreference object because its finalize object needs to be called, so its reference, even if it is in the queue, is not referent null, that is, it is not clear.

The Phantomreference object, because its own get implementation returns NULL. So clear does not work very well. Because no matter enqueue or not, it will not be cleared away.

Ten, Referencehandler enqueue thread

The above mentioned that the JVM will be working on the object set to the pending object, so there must be a thread to do the continuous enqueue operation, this thread refers to the processor thread, its priority is max_priority, that is, the highest. The corresponding startup process is created for static initialization, It can be understood that this thread is created and started when any of the reference objects or classes are used. The corresponding code looks like this:

static {
 Threadgroup TG = Thread.CurrentThread (). Getthreadgroup ();
 for (Threadgroup TGN = TG;
   TGN!= null;
   TG = tgn, TGN = Tg.getparent ());
 Thread handler = new Referencehandler (TG, "Reference handler");
 /* If There were a special system-only priority greater than
  * max_priority, it would is used
  here * * Handle
 R.setpriority (thread.max_priority);
 Handler.setdaemon (true);
 Handler.start ();
}

The highest priority can be understood as the need to constantly process reference objects. When you run a thread through Jstack, the corresponding reference handler refers to the thread that is initialized here, as follows:

Xi. JVM-related

In each of these processing points, it is related to the JVM's recycling process. The GC process is considered to work in conjunction with the corresponding reference. If you use a CMS collector, in the whole process mentioned above, it involves the preclean process, It also involves the softreference processing of the reference object, and it also needs to collaborate with the specific type. The corresponding JVM processing, with C + + code, needs to be properly adjusted.

12, summary

As with the Finalreference object, the entire reference and Referencequeue are a group of cooperative working groups that, in order to ensure different citation semantics, work with the JVM GC-related processes to eventually implement different scenarios and different reference levels.

In addition, the direct use of referencequeue, coupled with the open thread to monitor the queue is too cumbersome and complex. You can refer to the Finalizablereferencequeue implemented by Google Guava and the corresponding Finalizablereference object. You can simplify a little bit of processing. The above is the entire content of this article, I hope for everyone's study or work to bring certain help.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.