强引用软引用弱引用虚引用使用场景与注意事项

本文详细解析了Java中的四种引用类型:强引用、软引用、弱引用和虚引用的生成方式、释放时机及应用场景,特别关注了它们在内存管理、缓存实现和垃圾回收中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

强引用:

生成方式:
new 出来的对象。 Object object = new Object();

释放时机:
1.需要手动释放
object=null;
2.线程结束,只在本线程中的强引用会被gc标记为可回收。

用处
想随时获取到该对象,不想被垃圾回收器gc收回,符合大部分应用场景。

注意事项:

  1. 注意集合类型中的强引用的释放问题,如:
String strongReference = new String("refenrence");
List<String> list = new ArrayList<>();
list.add(strongReference);
list = null;

以上方式中,strongReference并没有被释放。
如想释放需进行以下操作:

String strongReference =null;

如ArrayList源码中的操作:

public E remove(int index) {
        rangeCheck(index);

        modCount++;
        E oldValue = elementData(index);

        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work

        return oldValue;
    }
  1. 被强引用的对象,gc即使报出OOM不会回收该对象。回收不当,可能会造成内存泄漏。

软引用:

生成方式

SoftReference<String> sr = new SoftReference<String>(new String("hello"));

释放时机
在内存不足时,gc回收掉该对象。

用处
可以用来做缓存,例如缓存图片,当内存不足时,自动被回收。

弱引用:

生成方式:

WeakReference<String> sr = new WeakReference<String>(new String("hello"));

释放时机
gc在扫描时,发现一个对象只存在弱引用,就会标记回收掉该对象。

用处
当你想使用一个对象,又不想影响该对象本来的生命周期时,可以使用弱引用。
见ThreadLocal 源码中的ThreadLocalMap:

static class ThreadLocalMap {

/**
* The entries in this hash map extend WeakReference, using
* its main ref field as the key (which is always a
* ThreadLocal object).  Note that null keys (i.e. entry.get()
* == null) mean that the key is no longer referenced, so the
* entry can be expunged from table.  Such entries are referred to
* as "stale entries" in the code that follows.
*/
    static class Entry extends WeakReference<ThreadLocal<?>> {
        /** The value associated with this ThreadLocal. */
        Object value;

        Entry(ThreadLocal<?> k, Object v) {
            super(k);
            value = v;
        }
    }
}

ThreadLocal中,获取到线程私有对象是通过线程持有的一个threadLocalMap,然后传入ThreadLocal当做key获取到对象的,这时候就有个问题,如果你在使用完ThreadLocal之后,将其置为null,这时候这个对象并不能被回收,因为他还有 ThreadLocalMap->entry->key的引用,直到该线程被销毁,但是这个线程很可能会被放到线程池中不会被销毁,这就产生了内存泄露,jdk是通过弱引用来解决的这个问题的,entry中对key的引用是弱引用,当你取消了ThreadLocal的强引用之后,他就只剩下一个弱引用了,所以也会被回收。

虚引用:

生成方式:

ReferenceQueue<String> queue = new ReferenceQueue<String>();
        PhantomReference<String> pr = new PhantomReference<String>(new String("hello"), queue);

释放时机
unknown

用处
它允许你知道具体何时其引用的对象从内存中移除。

注意事项:
1.任何时候get都返回null
2.虚引用必须与引用队列同时使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值