【问题标题】:Confusion regarding weak references in java [duplicate]关于java中弱引用的困惑[重复]
【发布时间】:2014-11-06 00:22:51
【问题描述】:

我正在尝试理解弱引用,我在 wiki 中看到了以下代码:

import java.lang.ref.WeakReference;

public class ReferenceTest {
    public static void main(String[] args) throws InterruptedException {

            WeakReference r = new WeakReference(new String("I'm here"));
            WeakReference sr = new WeakReference("I'm here");
            System.out.println("before gc: r=" + r.get() + ", static=" + sr.get());
            System.gc();
            Thread.sleep(100);

            // only r.get() becomes null
            System.out.println("after gc: r=" + r.get() + ", static=" + sr.get());

    }
}

有人可以告诉我为什么只有 r 变为空,即使它持有一个强引用(新字符串)?

【问题讨论】:

  • 我所知道的是弱引用不会被垃圾收集,而强引用是。既然如此,我不明白为什么 r 变为 null 而 sr 没有
  • 如果我的理论是正确的,存储在sr 中的字符串存储在字符串池中,因为它是使用字符串文字创建的。存储在 r 中的字符串不是,因为它是使用 new 关键字创建的。由于String是sr在String Pool中仍然被引用,所以认为是强引用(这是纯理论,没有亲自研究过)

标签: java reference weak-references


【解决方案1】:

第一个 WeakReference 变为 null,因为它是对新 String 对象的唯一引用,因此没有对它的强引用,它可以被收集。

第二个WeakReference不会变成null,因为它引用的对象是字符串字面量,Java语言规范要求被interned,导致它被字符串池强引用,阻止了它的垃圾回收.

【讨论】:

    【解决方案2】:
    WeakReference r = new WeakReference(new String("I'm here"));
    

    没有强烈引用此行。只有WeakReference r 知道这个对象,因此对new String("I'm here") 的唯一引用是WeakReference r 而没有其他人。

    WeakReference sr = new WeakReference("I'm here");
    

    当您在 Java 中像这样声明 String 内联时,它会为声明类提供对字符串字面量的隐式硬引用。这与 String interning 在 Java 中的工作方式有关,也是为什么如果您在类中的许多不同位置声明相同的字符串字面量,Java 将只创建对该字符串字面量的单个引用。

    另见this answer

    【讨论】:

    • 第二行不是“内联声明字符串”。它声明了一个局部变量,sr,它被初始化为指向一个指向literal字符串的WeakReference对象。 GC 不会回收字符串,因为与所有文字字符串一样,它具有来自库的内部字符串表的强引用。我不喜欢吹毛求疵,但不精确的语言是导致这些新手一无所知的主要因素。
    • 我专门指的是如何声明字符串本身,即。作为文字,而不是整行本身在做什么。我可能错误地假设sr 是一个局部变量这一事实已经被理解。
    猜你喜欢
    • 1970-01-01
    • 2020-12-25
    • 2016-04-29
    • 1970-01-01
    • 2018-04-10
    • 2012-07-12
    • 1970-01-01
    • 2022-01-14
    相关资源
    最近更新 更多