Home  >  Article  >  Java  >  Introduction to Reference usage in Java

Introduction to Reference usage in Java

黄舟
黄舟Original
2017-03-16 10:19:072084browse

This article mainly introduces relevant information about the detailed explanation of Reference usage in Java. Friends who need it can refer to

Java Reference detailed explanation

In jdk 1.2 and its Later, the four concepts of strong reference, soft reference, weak reference, and virtual reference were introduced. There are many explanations about these four concepts on the Internet, but most of them are conceptual and general. Today I analyzed it based on the code. First, let’s look at the definition and general explanation (reference types are in the package Java.lang.ref).

1. Strong Reference (StrongReference)

Strong reference will not be recycled by GC, and there is no actual corresponding type in java.lang.ref. For example:


 Object obj = new Object();

The obj reference here is a strong reference and will not be recycled by GC.

2. SoftReference

Soft reference will be recycled by GC when the JVM reports insufficient memory, otherwise it will not be recycled. It is precisely because of this Feature soft references are widely used in caching and pooling. Usage of soft reference:


Object obj = new Object();
SoftReference<Object> softRef = new SoftReference(obj);
// 使用 softRef.get() 获取软引用所引用的对象
Object objg = softRef.get();

3. Weak reference (WeakReference)

When GC discovers a weak reference object, The object referenced by WeakReference will be released. The usage of weak references is similar to soft references, but the recycling strategy is different.

  4. Phantom Reference (PhantomReference)

Once the GC discovers the virtual reference object, it will insert the PhantomReference object into the ReferenceQueuequeue, At this time, the object pointed to by PhantomReference has not been recycled by the GC, but will not be recycled until the ReferenceQueue is actually processed by you. Usage of virtual references:


Object obj = new Object();
ReferenceQueue<Object> refQueue = new ReferenceQueue<Object>();
PhantomReference<Object> phanRef = new PhantomReference<Object>(obj, refQueue);
// 调用phanRef.get()不管在什么情况下会一直返回null
Object objg = phanRef.get();
// 如果obj被置为null,当GC发现了虚引用,GC会将phanRef插入进我们之前创建时传入的refQueue队列
// 注意,此时phanRef所引用的obj对象,并没有被GC回收,在我们显式地调用refQueue.poll返回phanRef之后
// 当GC第二次发现虚引用,而此时JVM将phanRef插入到refQueue会插入失败,此时GC才会对obj进行回收
Reference<? extends Object> phanRefP = refQueue.poll();

After reading the simple definition, let’s test it with the code. Needless to say, strong references are also very clear. The description of soft references is also very clear. , the key is "weak reference" and "virtual reference".

Weak reference:


public static void main(String[] args) throws InterruptedException {
  Object obj = new Object();
  ReferenceQueue<Object> refQueue = new ReferenceQueue<Object>();
  WeakReference<Object> weakRef = new WeakReference<Object>(obj, refQueue);
  System.out.println(weakRef.get());
  System.out.println(refQueue.poll());
  obj = null;
  System.gc();
  System.out.println(weakRef.get());
  System.out.println(refQueue.poll());
}

Since System.gc() tells the JVM that this is a good time to perform GC, but The specific execution or not is determined by the JVM, so when the JVM decides to execute GC, the result is (in fact, this code will generally execute GC):


  java.lang.Object@de6ced
  null
  null
  java.lang.ref.WeakReference@1fb8ee3

From execution As a result, we get the obj object by calling weakRef.get(). Since GC is not executed, refQueue.poll() returns null. When we set obj = null; at this time, there is no reference to the obj object in the heap. , here the JVM performed a GC, we found through weakRef.get() that null was returned, and refQueue.poll() returned the WeakReference object, so the JVM inserted the weakRef into the refQueue queue after recycling obj.

Virtual reference:


public static void main(String[] args) throws InterruptedException {
  Object obj = new Object();
  ReferenceQueue<Object> refQueue = new ReferenceQueue<Object>();
  PhantomReference<Object> phanRef = new PhantomReference<Object>(obj, refQueue);
  System.out.println(phanRef.get());
  System.out.println(refQueue.poll());
  obj = null;
  System.gc();
  System.out.println(phanRef.get());
  System.out.println(refQueue.poll());
}

Similarly, when the JVM executes GC, the result is:


  null
  null
  null
  java.lang.ref.PhantomReference@1fb8ee3

From the execution results, we know that what we said before is correct. phanRef.get() will return null no matter what the circumstances. When the JVM executes GC and finds the virtual reference, the JVM obj is not recycled, but the PhantomReference object is inserted into the corresponding virtual reference queue refQueue. When calling refQueue.poll() to return the PhantomReference object, the poll method will first queue the PhantomReference's holding queue (ReferenceQueue142273b7a9f22d62ff20269d1d75c0e2) is set to NULL, the NULL object inherits from ReferenceQueue, and the enqueue(Reference paramReference) method is overwritten to return false, and when obj is discovered by GC again , the JVM will insert PhantomReference into the NULL queue and the insertion will fail and return false. At this time, the GC will recycle obj. In fact, we cannot tell whether obj is recycled through this code, but there is a sentence in the javadoc comment of PhantomReference that reads:

Once the garbage The collector decides that an object obj is phantom-reachable, it is being enqueued on the corresponding queue, but its referent is not cleared. That is, the reference queue of the phantom reference must explicitly be processed by some application code.

Translation (this sentence is very simple, I believe many people should understand it):

Once the GC decides a "obj" is virtual reachable, it (referring to PhantomReference) will be enqueued to the corresponding queue, but its reference has not been cleared. That is, the reference queue of virtual references must be explicitly handled by some application code.

The use of weak references and virtual references

  软引用很明显可以用来制作caching和pooling,而弱引用与虚引用呢?其实用处也很大,首先我们来看看弱引用,举个例子:


class Registry {
  private Set registeredObjects = new HashSet();
 
  public void register(Object object) {
    registeredObjects.add( object );
  }
}

所有我添加进 registeredObjects 中的object永远不会被GC回收,因为这里有个强引用保存在registeredObjects里,另一方面如果我把代码改为如下:


class Registry {
   private Set registeredObjects = new HashSet();
 
   public void register(Object object) {
     registeredObjects.add( new WeakReference(object) );
   }
 }

  现在如果GC想要回收registeredObjects中的object,便能够实现了,同样在使用HashMap如果想实现如上的效果,一种更好的实现是使用WeakHashMap。

而虚引用呢?我们先来看看javadoc的部分说明:

Phantom references are useful for implementing cleanup operations that are necessary before an object gets garbage-collected. They are sometimes more flexible than the finalize() method.

翻译一下:

虚引用在实现一个对象被回收之前必须做清理操作是很有用的。有时候,他们比finalize()方法更灵活。

很明显的,虚引用可以用来做对象被回收之前的清理工作。

The above is the detailed content of Introduction to Reference usage in Java. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn