WeakReference字符串没有垃圾收集?怎么样?

3 java weak-references

我正在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());

        }
}
Run Code Online (Sandbox Code Playgroud)

当它运行时,这就是结果

在gc之前:r =我在这里,静态=我在这里

在gc之后:r = null,static =我在这里

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

我只是好奇这是怎么发生的.

Ste*_*n C 6

不是因为字符串池本身.

真正的原因是ReferenceTest该类具有对表示"I'm here"文字的String对象的隐式硬引用.该硬引用意味着弱引用sr不会被垃圾收集1破坏.

事实上:

  • 即使没有对应于文字的String对象,也需要隐式引用.(它们合并...... JLS实际上需要这个......但是我说即使它们不是这样的引用也是必需的.另一种方法是Java在每次字符串文字表达式时都会使用一个新的String对象.评估.这将非常低效!!)

  • 字符串池内部使用弱引用的形式...以便可以对未引用的实习字符串进行垃圾回收.如果不是这种情况,那么每个新的实习字符串都将是内存泄漏.

无论如何......如果你小心地构造一个字符串而不使用字符串文字并实习它,就像这样:

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

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


1 - 理论上,导致类被卸载和垃圾收集可以摆脱对该字符串文字的最后可到达的硬引用.但是,如果在这种情况下发生了这种情况,那么您将超过您能够观察WeakReference对象状态的点.至少,使用您的示例代码.此外,除非使用自定义类加载器启动JVM,否则我认为不可能导致卸载入口类.这不是那种简单或有用的事情.