SoftReference软引用

SoftReference软引用示例代码 importjava lang ref SoftReferenc authorchenjc since2020 01 13 publicclassS 使用 JVM 参数 Xmx10m 运行程序 paramargs throwsI

示例代码:

import java.lang.ref.SoftReference; / * @author chenjc * @since 2020-01-13 */ public class SoftReferenceTest { 
    / * 使用JVM参数-Xmx10m运行程序 * * @param args * @throws InterruptedException */ public static void main(String[] args) throws InterruptedException { 
    User user = new User(1, "debo"); // 建立User对象的软引用 SoftReference<User> userSoftReference = new SoftReference<>(user); // 去掉强引用 user = null; System.out.println(userSoftReference.get()); // 手动触发GC System.gc(); System.out.println("第一次GC: " + userSoftReference.get()); // 分配适量内存空间,造成内存资源紧张,产生GC,同时又不会导致堆内存溢出 byte[] bytes = new byte[6 * 1024 * 1050]; System.out.println("第二次GC: " + userSoftReference.get()); } private static class User { 
    private Integer id; private String name; public User(Integer id, String name) { 
    this.id = id; this.name = name; } public Integer getId() { 
    return id; } public void setId(Integer id) { 
    this.id = id; } public String getName() { 
    return name; } public void setName(String name) { 
    this.name = name; } @Override public String toString() { 
    return "User{" + "id=" + id + ", name='" + name + '\'' + '}'; } } } 

使用JVM参数-Xmx10m运行此程序,输出如下:

User{id=1, name='debo'} 第一次GC: User{id=1, name='debo'} 第二次GC: null 

第一次GC的时候,软引用没有被回收,是因为这时候内存资源充足。第二次由于分配了较大的内存,导致GC,这时候由于内存资源紧张,软引用被回收了,也就是虽然User对象有一个软引用在引用着它,但User对象在此条件下也会被GC回收。所以软引用的对象在一定条件下可被回收,故软引用对象不会导致内存溢出。

软引用到底有没有被回收,可以通过给软引用一个ReferenceQueue来跟踪,将上面的代码片段稍作修改,如下:

import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; / * @author chenjc * @since 2020-01-13 */ public class SoftReferenceTest { 
    / * 使用JVM参数-Xmx10m运行程序 * * @param args * @throws InterruptedException */ public static void main(String[] args) throws InterruptedException { 
    User user = new User(1, "debo"); // 建立User对象的软引用 ReferenceQueue<User> userReferenceQueue = new ReferenceQueue<>(); UserSoftReference userSoftReference = new UserSoftReference(user, userReferenceQueue); // 去掉强引用 user = null; System.out.println(userSoftReference.get()); // 手动触发GC System.gc(); System.out.println("第一次GC: " + userSoftReference.get()); System.out.println("第一次GC队列: " + userReferenceQueue.remove(1000)); // 分配适量内存空间,造成内存资源紧张,产生GC,同时又不会导致堆内存溢出 byte[] bytes = new byte[6 * 1024 * 1055]; System.out.println("第二次GC: " + userSoftReference.get()); Reference<? extends User> reference = userReferenceQueue.remove(1000); if (reference != null) { 
    UserSoftReference userSoftReference1 = (UserSoftReference) reference; System.out.println("第二次GC队列: " + userSoftReference1.getId()); } } private static class User { 
    private Integer id; private String name; public User(Integer id, String name) { 
    this.id = id; this.name = name; } public Integer getId() { 
    return id; } public void setId(Integer id) { 
    this.id = id; } public String getName() { 
    return name; } public void setName(String name) { 
    this.name = name; } @Override public String toString() { 
    return "User{" + "id=" + id + ", name='" + name + '\'' + '}'; } } private static class UserSoftReference extends SoftReference<User> { 
    private Integer id; public UserSoftReference(User referent, ReferenceQueue<? super User> q) { 
    super(referent, q); this.id = referent.id; } public Integer getId() { 
    return id; } public void setId(Integer id) { 
    this.id = id; } } } 

输出如下:

User{id=1, name='debo'} 第一次GC: User{id=1, name='debo'} 第一次GC队列: null 第二次GC: null 第二次GC队列: 1 

第一次GC没有回收软引用对象,所以ReferenceQueue为空,第二次GC回收了软引用对象,所以ReferenceQueue队列不为空,那为什么可以强转成UserSoftReference呢?是因为队列里面的reference就是方法局部变量userSoftReference。此处自定义一个UserSoftReference类主要是为了跟踪User对象的id,你无法跟踪User对象,因为User对象已经被回收了,如果调用reference.get(),将会返回null。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/219785.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 下午9:54
下一篇 2026年3月17日 下午9:54


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号