Introduction and demonstration of Java’s four reference types

I. Introduction

Java has four reference types: strong reference, soft reference, weak reference, and virtual reference. The default statement in Java is the strong reference. The one we use most is the strong reference. Here we will explain and demonstrate each reference relationship.

  • Prepare one in advance UserNeeded for use in class demonstrations
public class User {
    
    
    private Long id;
}

2. Java’s four reference types

StrongReference

The default statement in Java is a strong reference, such as:

User user = new User(); // 创建一个User对象,使用强引用
System.gc(); // 手动触发GC
if(user == null){
    
    
    System.out.println("user对象已经被GC回收    " + user);
}else {
    
    
    System.out.println("user对象没有被GC回收    " + user);
}
user = null; // 手动置null 取消引用

As long as a strong reference exists, the garbage collector will never recycle the referenced object. Even when there is insufficient memory, the JVM will directly throw an OutOfMemoryError and will not recycle it. If you want to break the connection between the strong reference and the object, you can explicitly assign the strong reference to null, so that the JVM can recycle the object in a timely manner.

SoftReference

If an object only has soft references, when the memory space is sufficient, even if garbage collection is manually triggered, it will not be recycled; if the memory space is insufficient, the memory of these objects will be recycled. As long as the garbage collector does not collect it, the object can be used by the program. Soft references can be used to implement memory-sensitive caches.

To simulate this effect, you need to set the heap memory size in the startup parameters:

-Xmx1M -Xms1M
SoftReference<User> softRef = new SoftReference(new User()); // 软引用
System.gc(); // 手动触发GC
if(softRef.get() == null){
    
    
    System.out.println("user对象已经被GC回收    " + softRef.get());
}else {
    
    
    System.out.println("user对象没有被GC回收    " + softRef.get());
}
// 模拟内存溢出 这里创建1M的Byte数组
try {
    
    
    Byte[] bytes = new Byte[1024 * 1024 * 1024];
}catch (OutOfMemoryError e){
    
    
    e.printStackTrace();
}
if(softRef.get() == null){
    
    
    System.out.println("user对象已经被GC回收    " + softRef.get());
}else {
    
    
    System.out.println("user对象没有被GC回收    " + softRef.get());
}

Soft references can be used in conjunction with ReferenceQueue. When the soft reference object is recycled due to insufficient system memory, the JVM will add the soft reference SoftReference object to the associated ReferenceQueue. In addition to the special function of saving soft references, the SoftReference object In addition to its properties, it also has the generality of Java objects. Therefore, when the soft-accessible object is recycled, although the get() method of the SoftReference object returns null, the SoftReference object no longer has existing value, and an appropriate clearing mechanism is needed to avoid the memory caused by a large number of SoftReference objects. Leak, use ReferenceQueue to clear the lost soft reference object SoftReference.

ReferenceQueue referenceQueue = new ReferenceQueue(); // 引用队列
SoftReference<User> softRef = new SoftReference(new User(),referenceQueue); // 软引用
System.gc(); // 手动触发GC
if(softRef.get() == null){
    
    
    System.out.println("user对象已经被GC回收    " + softRef.get());
}else {
    
    
    System.out.println("user对象没有被GC回收    " + softRef.get());
}
// 模拟内存溢出 这里创建1M的Byte数组
try {
    
    
    Byte[] bytes = new Byte[1024 * 1024 * 1024];
}catch (OutOfMemoryError e){
    
    
    e.printStackTrace();
}
if(softRef.get() == null){
    
    
    System.out.println("user对象已经被GC回收    " + softRef.get());
}else {
    
    
    System.out.println("user对象没有被GC回收    " + softRef.get());
}
// 当软引用User对象被回收后 referenceQueue.poll() 能获取到软引用SoftReference对象
if(softRef == referenceQueue.poll()){
    
    
    softRef = null;
}

WeakReference

Objects with only weak references will be recycled when the JVM triggers gc. Unlike soft references, weak references will be recycled regardless of whether there is insufficient memory. Weak references can also be used in conjunction with ReferenceQueue. When the system triggers gc and the weakly referenced object is recycled, the JVM will add the weakly referenced WeakReference object to the associated ReferenceQueue. However, due to the priority of the garbage collector thread The level is very low, so weak references may not be recycled quickly.

WeakReference<User> weakRef = new WeakReference(new User()); // 弱引用
if(weakRef.get() == null){
    
    
    System.out.println("user对象已经被GC回收    " + weakRef.get());
}else {
    
    
    System.out.println("user对象没有被GC回收    " + weakRef.get());
}
System.gc(); // 手动触发GC
if(weakRef.get() == null){
    
    
    System.out.println("user对象已经被GC回收    " + weakRef.get());
}else {
    
    
    System.out.println("user对象没有被GC回收    " + weakRef.get());
}

PhantomReference

Virtual references are mainly used to track the activity of objects being recycled by the garbage collector. One difference between virtual references, soft references and weak references is that virtual references must be used in conjunction with a reference queue (ReferenceQueue). When the garbage collector recycles an object, if it finds that it still has a virtual reference, it will add the virtual reference to the reference queue associated with it. The program can learn whether the referenced object will be garbage collected by determining whether a virtual reference has been added to the reference queue. If the program discovers that a virtual reference has been added to the reference queue, it can take necessary actions before the memory of the referenced object is reclaimed. Due to the insecurity and inefficiency of the Object.finalize() method, virtual references are often used to release resources before object recycling.

User user = new User(); //创建一个强引用对象
ReferenceQueue referenceQueue = new ReferenceQueue(); // 引用队列
PhantomReference<User> phantomReference = new PhantomReference<>(user, referenceQueue); // 使用虚引用指向这个内存空间 并且绑定引用队列
System.out.println(phantomReference.get()); // 虚引用是获取不到引用值的 get方法返回的null
user = null; // 释放这个内存空间,此时只剩phantomReference通过虚引用指向它
System.gc(); // 手动触发GC
// 被清除的队列中取出被回收的对象
while (true) {
    
    
    Reference<? extends User> poll = referenceQueue.poll();
    if (poll!=null) {
    
    
        System.out.println("虚引用对象被回收 处理其它逻辑");
         return;
    }
}

3. Summary

The levels of Java's four reference types from high to low are: strong reference > soft reference > weak reference > virtual reference

level Recycling time use
strong reference Will not be recycled All direct quotes
soft reference Recycle when memory is low Combined with ReferenceQueue to construct a secondary high-speed buffer for objects with short validity period/large memory footprint/long life cycle (cleared only when the memory is insufficient)
weak quotation During garbage collection Combined with ReferenceQueue to construct a first-level high-speed buffer for objects with short validity period/large memory footprint/long life cycle (cleared when GC occurs in the system)
virtual reference During garbage collection Combined with ReferenceQueue to track the activity of objects being recycled by the garbage collector

Guess you like

Origin blog.csdn.net/weixin_44606481/article/details/134808603