gpt4 book ai didi

java - WeakReference 字符串没有被垃圾回收?如何?

转载 作者:塔克拉玛干 更新时间:2023-11-01 22:50:11 24 4
gpt4 key购买 nike

我在维基百科上阅读有关 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());

}
}

当它运行时,这是结果

before gc: r=I'm here, static=I'm here

after gc: r=null, static=I'm here

srr 变量都是引用字符串对象。 r 现在被垃圾收集了,但是为什么 sr 在调用垃圾收集器后没有被垃圾收集?

我很好奇这是怎么发生的。

最佳答案

不是因为字符串池本身

真正的原因是 ReferenceTest 类对表示 “我在这里” 文字的 String 对象有一个隐式硬引用。该硬引用意味着 sr 中的弱引用不会被垃圾回收1 破坏。

事实上:

  • 隐式引用是必要的,即使对应于文字的 String 对象没有被合并。 (他们汇集...JLS有效地需要这个...但我是说即使他们不是,也需要引用。替代方案是每次评估字符串文字表达式时,Java 都会创建并“实习”一个新的 String 对象。那将是可怕的低效!!)

  • 字符串池在内部使用一种弱引用形式...这样未引用的驻留字符串就可以被垃圾回收。如果不是这种情况,那么调用 String.intern() 可能会导致无法治愈的内存泄漏。

无论如何...如果您在不使用字符串字面量的情况下仔细构造一个字符串并将其保留,如下所示:

    char[] chars = {'a', 'b', 'c'};
WeakReference r = new WeakReference(new String(chars).intern());

...您应该发现弱引用(最终)被破坏了。 (虽然这可能需要几个 GC 周期。)


1 - 理论上,导致类被卸载和垃圾收集可以摆脱对该字符串文字的最后一个可访问的硬引用。但是,如果这种情况发生在这种情况下,您将无法观察到 WeakReference 对象的状态。至少,在您的示例代码中。此外,除非您使用自定义类加载器启动 JVM,否则我认为不可能导致入口点类的卸载。这不是一件容易做或有用的事情。

关于java - WeakReference 字符串没有被垃圾回收?如何?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14494875/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com