JAVA中的引用类型

强引用

1.JAVA中默认为强引用

Object obj = new Object(); //只要obj指向object对象,Object对象就不会被回收
obj = null; //置位null,被回收

软引用

1.软引用是用来描述一些非必需但仍然有用的对象。当内存足够的时候,软引用不会回收。只有在内存不够的情况下,才会回收软引用。当回收了软引用内存还是不够,会抛出内存溢出。这种特性常常被用作缓存技术,比如网页缓存,图片缓存等。

下面举例来说明强引用和软引用的区别
在运行java代码之前,设置虚拟机的运行内存 -Xms2M -Xmx3M初始内存为2M最大内存为3M。
在这里插入图片描述
在这里插入图片描述

使用强引用正常情况下

public class TestOOM {
    public static void main(String[] args) {
        testStrongReference();
    }

    private static void testStrongReference() {
        // 当 new byte为 1M 时,程序运行正常
        byte[] buff = new byte[1024 * 1024 * 2];
        System.out.println("当强引用设置内存为2M的时候");
    }
}

运行结果

正常输出:当强引用设置内存为2M的时候

使用强引用超出内存限制情况

public class TestOOM {
    public static void main(String[] args) {
        testStrongReference();
    }

    private static void testStrongReference() {
        // 当 new byte为 1M 时,程序运行正常
        byte[] buff = new byte[1024 * 1024 * 3];
        System.out.println("当强引用设置内存为2M的时候");
    }
}

运行结果

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at com.practise.workhome.TestOOM.testStrongReference(TestOOM.java:10)
	at com.practise.workhome.TestOOM.main(TestOOM.java:5)

Process finished with exit code 1

使用软引用正常的情况下

1.使用软引用,连续创建2个大小为1M的字节数组,并且赋值为软引用

public class TestOOM {
    private static List<Object> list = new ArrayList<>();
    public static void main(String[] args) {
        testSoftReference();
    }
    private static void testSoftReference() {
        for (int i = 0; i < 2; i++) {
            byte[] buff = new byte[1024 * 1024];
            SoftReference<byte[]> sr = new SoftReference<>(buff);
            list.add(sr);
        }

        for(int i=0; i < list.size(); i++){
            Object obj = ((SoftReference) list.get(i)).get();
            System.out.println(obj);
        }
    }
}

运行结果

[B@6d6f6e28
[B@135fbaa4

使用软引用异常的情况下

1.使用软引用连续创建3个1M的数组,并赋值为软引用

public class TestOOM {
    private static List<Object> list = new ArrayList<>();
    public static void main(String[] args) {
        testSoftReference();
    }
    private static void testSoftReference() {
        for (int i = 0; i < 3; i++) {
            byte[] buff = new byte[1024 * 1024];
            SoftReference<byte[]> sr = new SoftReference<>(buff);
            list.add(sr);
        }

        for(int i=0; i < list.size(); i++){
            Object obj = ((SoftReference) list.get(i)).get();
            System.out.println(obj);
        }
    }
}

运行结果

null
null
[B@6d6f6e28

注意:在代码中buff是一个强引用,它最终是指向软引用,软引用被回收后编译器发现buff没有被使用,自行进行优化回收了。

如果我们将代码做下调整

public class TestOOM {
    private static List<Object> list = new ArrayList<>();
   
    public static void main(String[] args) {
        testSoftReference();
    }
    private static void testSoftReference() {
        byte[] buff = null;
        for (int i = 0; i < 3; i++) {
            buff = new byte[1024 * 1024];
            SoftReference<byte[]> sr = new SoftReference<>(buff);
            list.add(sr);
        }

        for(int i=0; i < list.size(); i++){
            Object obj = ((SoftReference) list.get(i)).get();
            System.out.println(obj);
        }
    }
}

运行结果

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at com.practise.workhome.TestOOM.testSoftReference(TestOOM.java:16)
	at com.practise.workhome.TestOOM.main(TestOOM.java:11)
  • 结论:当软引用超出内存,打印结果总是最后一个对象被保存,其他的obj全部被置空了;说明软引用在内存不足的情况下,会自动被回收。

弱引用

弱引用的引用强度比软引用更弱一些,无论内存是否足够,只要JVM开始垃圾回收被弱引用关联的对象都会被回收。
示例代码

public class TestOOM {
    private static List<Object> list = new ArrayList<>();

    public static void main(String[] args) {
        testWeakReference();
    }
    private static void testWeakReference() {
        for (int i = 0; i < 10; i++) {
            byte[] buff = new byte[1024 * 1024];
            WeakReference<byte[]> sr = new WeakReference<>(buff);
            list.add(sr);
        }

        System.gc(); //主动通知垃圾回收

        for(int i=0; i < list.size(); i++){
            Object obj = ((WeakReference) list.get(i)).get();
            System.out.println(obj);
        }
    }
}

运行结果

null
null
null
null
null
null
null
null
null
null

虚引用

虚引用是最弱的一种引用关系,如果一个对象仅持有虚引用那么等同于没有。虚引用使用类PhantomReference来表示,这个类有一个构造方法和get()方法,而他的get()方法返回的是null,也就是说无法使用get获取任何对象,虚引用必须结合ReferenceQueue一起使用;

/*
 * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package java.lang.ref;


/**
 * Phantom reference objects, which are enqueued after the collector
 * determines that their referents may otherwise be reclaimed.  Phantom
 * references are most often used for scheduling pre-mortem cleanup actions in
 * a more flexible way than is possible with the Java finalization mechanism.
 *
 * <p> If the garbage collector determines at a certain point in time that the
 * referent of a phantom reference is <a
 * href="package-summary.html#reachability">phantom reachable</a>, then at that
 * time or at some later time it will enqueue the reference.
 *
 * <p> In order to ensure that a reclaimable object remains so, the referent of
 * a phantom reference may not be retrieved: The <code>get</code> method of a
 * phantom reference always returns <code>null</code>.
 *
 * <p> Unlike soft and weak references, phantom references are not
 * automatically cleared by the garbage collector as they are enqueued.  An
 * object that is reachable via phantom references will remain so until all
 * such references are cleared or themselves become unreachable.
 *
 * @author   Mark Reinhold
 * @since    1.2
 */

public class PhantomReference<T> extends Reference<T> {

    /**
     * Returns this reference object's referent.  Because the referent of a
     * phantom reference is always inaccessible, this method always returns
     * <code>null</code>.
     *
     * @return  <code>null</code>
     */
    public T get() {
        return null;
    }

    /**
     * Creates a new phantom reference that refers to the given object and
     * is registered with the given queue.
     *
     * <p> It is possible to create a phantom reference with a <tt>null</tt>
     * queue, but such a reference is completely useless: Its <tt>get</tt>
     * method will always return null and, since it does not have a queue, it
     * will never be enqueued.
     *
     * @param referent the object the new phantom reference will refer to
     * @param q the queue with which the reference is to be registered,
     *          or <tt>null</tt> if registration is not required
     */
    public PhantomReference(T referent, ReferenceQueue<? super T> q) {
        super(referent, q);
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值