Java强引用、软引用、弱引用、虚引用详解

本文详细介绍了Java中的四种引用类型:强引用、软引用、弱引用和虚引用,并提供了每种引用类型的定义、特点及应用场景。此外,还提供了一段示例代码帮助理解不同引用类型的行为。

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

Java中没有指针的概念,而引用就是一个弱化的指针,保证开发不能任意操作内存。最近整理了一下之前不明白的各种级别引用:强引用、软引用、弱引用、虚引用,它们的特点和应用场景汇总如下:
1、强引用
如果一个对象具有强引用,GC绝不会回收它;当内存空间不足,JVM宁愿抛出OutOfMemoryError错误。一般new出来的对象都是强引用,如下

<code class="hljs cs has-numbering"><span class="hljs-comment">//强引用 </span>
User strangeReference=<span class="hljs-keyword">new</span> User();  </code><ul style="" class="pre-numbering"><li>1</li><li>2</li></ul>

2、软引用
如果一个对象具有软引用,当内存空间不足,GC会回收这些对象的内存,使用软引用构建敏感数据的缓存。
在JVM中,软引用是如下定义的,可以通过一个时间戳来回收,下面引自JVM:

<code class="hljs scala has-numbering">    public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SoftReference</span><<span class="hljs-title">T</span>> <span class="hljs-keyword">extends</span> <span class="hljs-title">Reference</span><<span class="hljs-title">T</span>> {</span>

    <span class="hljs-javadoc">/**
     * Timestamp clock, updated by the garbage collector
     */</span>
    static <span class="hljs-keyword">private</span> long clock;

    <span class="hljs-javadoc">/**
     * Timestamp updated by each invocation of the get method.  The VM may use
     * this field when selecting soft references to be cleared, but it is not
     * required to do so.
     */</span>
    <span class="hljs-keyword">private</span> long timestamp;

    <span class="hljs-javadoc">/**
     * Creates a new soft reference that refers to the given object.  The new
     * reference is not registered with any queue.
     *
     * <span class="hljs-javadoctag">@param</span> referent object the new soft reference will refer to
     */</span>
    public SoftReference(T referent) {
        <span class="hljs-keyword">super</span>(referent);
        <span class="hljs-keyword">this</span>.timestamp = clock;
    }

    <span class="hljs-javadoc">/**
     * Creates a new soft reference that refers to the given object and is
     * registered with the given queue.
     *
     * <span class="hljs-javadoctag">@param</span> referent object the new soft reference will refer to
     * <span class="hljs-javadoctag">@param</span> q the queue with which the reference is to be registered,
     *          or <tt>null</tt> if registration is not required
     *
     */</span>
    public SoftReference(T referent, ReferenceQueue<? <span class="hljs-keyword">super</span> T> q) {
        <span class="hljs-keyword">super</span>(referent, q);
        <span class="hljs-keyword">this</span>.timestamp = clock;
    }

    <span class="hljs-javadoc">/**
     * Returns this reference object's referent.  If this reference object has
     * been cleared, either by the program or by the garbage collector, then
     * this method returns <code>null</code>.
     *
     * <span class="hljs-javadoctag">@return</span>   The object to which this reference refers, or
     *           <code>null</code> if this reference object has been cleared
     */</span>
    public T get() {
        T o = <span class="hljs-keyword">super</span>.get();
        <span class="hljs-keyword">if</span> (o != <span class="hljs-keyword">null</span> && <span class="hljs-keyword">this</span>.timestamp != clock)
            <span class="hljs-keyword">this</span>.timestamp = clock;
        <span class="hljs-keyword">return</span> o;
    }

}
</code>

软引用的声明的借助强引用或者匿名对象,使用泛型SoftReference;可以通过get方法获得强引用。具体如下:

<code class="hljs cs has-numbering"><span class="hljs-comment">//软引用</span>
SoftReference<User>softReference=<span class="hljs-keyword">new</span> SoftReference<User>(<span class="hljs-keyword">new</span> User());
strangeReference=softReference.<span class="hljs-keyword">get</span>();<span class="hljs-comment">//通过get方法获得强引用</span></code>

3、弱引用
如果一个对象具有弱引用,在GC线程扫描内存区域的过程中,不管当前内存空间足够与否,都会回收内存,使用弱引用 构建非敏感数据的缓存。
在JVM中,弱引用是如下定义的,下面引自JVM:

<code class="hljs scala has-numbering">public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">WeakReference</span><<span class="hljs-title">T</span>> <span class="hljs-keyword">extends</span> <span class="hljs-title">Reference</span><<span class="hljs-title">T</span>> {</span>

    <span class="hljs-javadoc">/**
     * Creates a new weak reference that refers to the given object.  The new
     * reference is not registered with any queue.
     *
     * <span class="hljs-javadoctag">@param</span> referent object the new weak reference will refer to
     */</span>
    public WeakReference(T referent) {
        <span class="hljs-keyword">super</span>(referent);
    }

    <span class="hljs-javadoc">/**
     * Creates a new weak reference that refers to the given object and is
     * registered with the given queue.
     *
     * <span class="hljs-javadoctag">@param</span> referent object the new weak reference will refer to
     * <span class="hljs-javadoctag">@param</span> q the queue with which the reference is to be registered,
     *          or <tt>null</tt> if registration is not required
     */</span>
    public WeakReference(T referent, ReferenceQueue<? <span class="hljs-keyword">super</span> T> q) {
        <span class="hljs-keyword">super</span>(referent, q);
    }

}</code>
弱引用的声明的借助强引用或者匿名对象,使用泛型WeakReference<T>,具体如下:
<code class="hljs cs has-numbering"><span class="hljs-comment">//弱引用</span>
WeakReference<User>weakReference=<span class="hljs-keyword">new</span> WeakReference<User>(<span class="hljs-keyword">new</span> User());</code>

4、虚引用
如果一个对象仅持有虚引用,在任何时候都可能被垃圾回收,虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列联合使用,虚引用主要用来跟踪对象 被垃圾回收的活动。
在JVM中,虚引用是如下定义的,下面引自JVM:

<code class="hljs applescript has-numbering">    public <span class="hljs-type">class</span> PhantomReference<T> extends Reference<T> {

    /**
     * Returns this <span class="hljs-keyword">reference</span> object's referent.  Because <span class="hljs-keyword">the</span> referent <span class="hljs-keyword">of</span> a
     * phantom <span class="hljs-keyword">reference</span> <span class="hljs-keyword">is</span> always inaccessible, this method always returns
     * <code>null</code>.
     *
     * @<span class="hljs-constant">return</span>  <code>null</code>
     */
    public T <span class="hljs-keyword">get</span>() {
<span class="hljs-command">        return</span> null;
    }

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

}</code>
虚引用PhantomReference<T>的声明的借助强引用或者匿名对象,结合泛型ReferenceQueue<T>初始化,具体如下:
<code class="hljs cs has-numbering"><span class="hljs-comment">//虚引用</span>
PhantomReference<User> phantomReference=<span class="hljs-keyword">new</span> PhantomReference<User>(<span class="hljs-keyword">new</span> User(),<span class="hljs-keyword">new</span> ReferenceQueue<User>());</code>

5、总结
下面是一段关于强引用、软引用、弱引用、虚引用的程序:

<code class="hljs cs has-numbering">import java.lang.<span class="hljs-keyword">ref</span>.*;
import java.util.HashSet;
import java.util.Set;

class User {

    <span class="hljs-keyword">private</span> String name;

    <span class="hljs-keyword">public</span> <span class="hljs-title">User</span>()
    {}

    <span class="hljs-keyword">public</span> <span class="hljs-title">User</span>(String name)
    {
        <span class="hljs-keyword">this</span>.name=name;
    }

    @Override
    <span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span>() {
        <span class="hljs-keyword">return</span> name;
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">finalize</span>(){
        System.<span class="hljs-keyword">out</span>.println(<span class="hljs-string">"Finalizing ... "</span>+name);
    }
}

<span class="hljs-comment">/**
 * Created by jinxu on 15-4-25.
 */</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> ReferenceDemo {

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> ReferenceQueue<User> referenceQueue = <span class="hljs-keyword">new</span> ReferenceQueue<User>();
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> final <span class="hljs-keyword">int</span> size = <span class="hljs-number">10</span>;

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">checkQueue</span>(){
       <span class="hljs-comment">/* Reference<? extends User> reference = null;
        while((reference = referenceQueue.poll())!=null){
            System.out.println("In queue : "+reference.get());
        }*/</span>
        Reference<? extends User> reference = referenceQueue.poll();
        <span class="hljs-keyword">if</span>(reference!=<span class="hljs-keyword">null</span>){
            System.<span class="hljs-keyword">out</span>.println(<span class="hljs-string">"In queue : "</span>+reference.<span class="hljs-keyword">get</span>());
        }
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testSoftReference</span>()
    {
        Set<SoftReference<User>> softReferenceSet = <span class="hljs-keyword">new</span> HashSet<SoftReference<User>>();
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < size; i++) {
            SoftReference<User> <span class="hljs-keyword">ref</span> = <span class="hljs-keyword">new</span> SoftReference<User>(<span class="hljs-keyword">new</span> User(<span class="hljs-string">"Soft "</span> + i), referenceQueue);
            System.<span class="hljs-keyword">out</span>.println(<span class="hljs-string">"Just created: "</span> + <span class="hljs-keyword">ref</span>.<span class="hljs-keyword">get</span>());
            softReferenceSet.add(<span class="hljs-keyword">ref</span>);
        }
        System.gc();
        checkQueue();
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testWeaKReference</span>()
    {
        Set<WeakReference<User>> weakReferenceSet = <span class="hljs-keyword">new</span> HashSet<WeakReference<User>>();
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < size; i++) {
            WeakReference<User> <span class="hljs-keyword">ref</span> = <span class="hljs-keyword">new</span> WeakReference<User>(<span class="hljs-keyword">new</span> User(<span class="hljs-string">"Weak "</span> + i), referenceQueue);
            System.<span class="hljs-keyword">out</span>.println(<span class="hljs-string">"Just created: "</span> + <span class="hljs-keyword">ref</span>.<span class="hljs-keyword">get</span>());
            weakReferenceSet.add(<span class="hljs-keyword">ref</span>);
        }
        System.gc();
        checkQueue();
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testPhantomReference</span>()
    {
        Set<PhantomReference<User>> phantomReferenceSet = <span class="hljs-keyword">new</span> HashSet<PhantomReference<User>>();
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < size; i++) {
            PhantomReference<User> <span class="hljs-keyword">ref</span> =
                    <span class="hljs-keyword">new</span> PhantomReference<User>(<span class="hljs-keyword">new</span> User(<span class="hljs-string">"Phantom "</span> + i), referenceQueue);
            System.<span class="hljs-keyword">out</span>.println(<span class="hljs-string">"Just created: "</span> + <span class="hljs-keyword">ref</span>.<span class="hljs-keyword">get</span>());
            phantomReferenceSet.add(<span class="hljs-keyword">ref</span>);
        }
        System.gc();
        checkQueue();
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span>(String[] args) {
        testSoftReference();
        testWeaKReference();
        testPhantomReference();
    }
}</code>

结果为

<code class="hljs r has-numbering">Just created: Soft <span class="hljs-number">0</span>
Just created: Soft <span class="hljs-number">1</span>
Just created: Soft <span class="hljs-number">2</span>
Just created: Soft <span class="hljs-number">3</span>
Just created: Soft <span class="hljs-number">4</span>
Just created: Soft <span class="hljs-number">5</span>
Just created: Soft <span class="hljs-number">6</span>
Just created: Soft <span class="hljs-number">7</span>
Just created: Soft <span class="hljs-number">8</span>
Just created: Soft <span class="hljs-number">9</span>
Just created: Weak <span class="hljs-number">0</span>
Just created: Weak <span class="hljs-number">1</span>
Just created: Weak <span class="hljs-number">2</span>
Just created: Weak <span class="hljs-number">3</span>
Just created: Weak <span class="hljs-number">4</span>
Just created: Weak <span class="hljs-number">5</span>
Just created: Weak <span class="hljs-number">6</span>
Just created: Weak <span class="hljs-number">7</span>
Just created: Weak <span class="hljs-number">8</span>
Just created: Weak <span class="hljs-number">9</span>
Finalizing <span class="hljs-keyword">...</span> Weak <span class="hljs-number">7</span>
Finalizing <span class="hljs-keyword">...</span> Weak <span class="hljs-number">8</span>
Finalizing <span class="hljs-keyword">...</span> Weak <span class="hljs-number">9</span>
Finalizing <span class="hljs-keyword">...</span> Weak <span class="hljs-number">4</span>
Finalizing <span class="hljs-keyword">...</span> Weak <span class="hljs-number">5</span>
Finalizing <span class="hljs-keyword">...</span> Weak <span class="hljs-number">6</span>
Finalizing <span class="hljs-keyword">...</span> Weak <span class="hljs-number">0</span>
Finalizing <span class="hljs-keyword">...</span> Weak <span class="hljs-number">1</span>
Finalizing <span class="hljs-keyword">...</span> Weak <span class="hljs-number">2</span>
Finalizing <span class="hljs-keyword">...</span> Weak <span class="hljs-number">3</span>
Finalizing <span class="hljs-keyword">...</span> Soft <span class="hljs-number">9</span>
Finalizing <span class="hljs-keyword">...</span> Soft <span class="hljs-number">8</span>
Finalizing <span class="hljs-keyword">...</span> Soft <span class="hljs-number">7</span>
Finalizing <span class="hljs-keyword">...</span> Soft <span class="hljs-number">6</span>
Finalizing <span class="hljs-keyword">...</span> Soft <span class="hljs-number">5</span>
Finalizing <span class="hljs-keyword">...</span> Soft <span class="hljs-number">4</span>
Finalizing <span class="hljs-keyword">...</span> Soft <span class="hljs-number">3</span>
Finalizing <span class="hljs-keyword">...</span> Soft <span class="hljs-number">2</span>
Finalizing <span class="hljs-keyword">...</span> Soft <span class="hljs-number">1</span>
Finalizing <span class="hljs-keyword">...</span> Soft <span class="hljs-number">0</span>
In queue : null
Just created: null
Just created: null
Just created: null
Just created: null
Just created: null
Just created: null
Just created: null
Just created: null
Just created: null
Just created: null
In queue : null
Finalizing <span class="hljs-keyword">...</span> Phantom <span class="hljs-number">9</span>
Finalizing <span class="hljs-keyword">...</span> Phantom <span class="hljs-number">7</span>
Finalizing <span class="hljs-keyword">...</span> Phantom <span class="hljs-number">8</span>
Finalizing <span class="hljs-keyword">...</span> Phantom <span class="hljs-number">4</span>
Finalizing <span class="hljs-keyword">...</span> Phantom <span class="hljs-number">5</span>
Finalizing <span class="hljs-keyword">...</span> Phantom <span class="hljs-number">6</span>
Finalizing <span class="hljs-keyword">...</span> Phantom <span class="hljs-number">0</span>
Finalizing <span class="hljs-keyword">...</span> Phantom <span class="hljs-number">1</span>
Finalizing <span class="hljs-keyword">...</span> Phantom <span class="hljs-number">2</span>
Finalizing <span class="hljs-keyword">...</span> Phantom <span class="hljs-number">3</span>
</code>

转自:http://blog.youkuaiyun.com/xiaofengcanyuexj/article/details/45271195

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值