1

I'm trying to understand weak references and I saw the following code in 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());

    }
}

Could someone please tell me why only r becomes null even though it's holding a strong reference (new string)?

attaboy182
  • 2,039
  • 3
  • 22
  • 28
  • All I know is weak references are not prevented from being garbage collected while strong references are. That being the case, I don't understand why r becomes null while sr doesn't – attaboy182 Nov 06 '14 at 00:27
  • 1
    If my theory is correct, the String stored in `sr` is stored in the String Pool, since it's created using a String Literal. The String stored in r is not, since it's created using the `new` keyword. Since the String is `sr` is still referenced in the String Pool, it's considered to be referenced strongly (this is pure theory; havent dug into it personally) – Vince Nov 06 '14 at 00:32

2 Answers2

5

The first WeakReference becomes null because it is the only reference to the new String object, so there are no strong references to it, and it becomes eligible for collection.

The second WeakReference does not become null because the object it refers to is a string literal, which is required by the Java language specification to be interned, which causes it to be strongly referenced from the string pool, which prevents its garbage collection.

meriton
  • 68,356
  • 14
  • 108
  • 175
2
WeakReference r = new WeakReference(new String("I'm here"));

There is no strong reference to this line. Only the WeakReference r knows about this object, and thus the only references to new String("I'm here") is the WeakReference r and no one else.

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

When you declare a String inline like this in Java, it gives the declaring class an implicit hard reference to the String literal. This is related to how String interning works in Java and is also why if you declare the same String literal in many difference places in a class, Java will create only a single reference to that String literal.

See also this answer

Community
  • 1
  • 1
Jeffrey Mixon
  • 12,846
  • 4
  • 32
  • 55
  • 2nd line is not "declaring a string in-line". It is declaring a _local variable_, `sr`, that is initialized to point to a WeakReference object, that refers to a _literal_ String. The String is not reclaimed by the GC because, like all literal Strings, it has a strong reference from the library's table of interned strings. I don't like being nit-picky, but imprecise language is a major contributing factor to the cluelessness of these newbies. – Solomon Slow Nov 06 '14 at 01:45
  • I was referring specifically to how the String itself is being declared, viz. as a literal, and not what the entire line itself is doing. I was, perhaps erroneously, operating under the assumption that the fact that `sr` is a local variable was already understood. – Jeffrey Mixon Nov 06 '14 at 01:55