1

In the following snippet (whose only purpose is educational testing), contains() always ↲ true.

    Set<String> weakSet = Collections.newSetFromMap(new WeakHashMap<>());
    weakSet.add("someKey");
    System.gc();
    weakSet.contains("someKey");

I would expect that the best effort done by the JVM to reclaim space includes removing objects that are only weakly reachable (weak set elements without any strong references). But I'm wrong.

So, is there a way to test in practice the automatic removal of weak references, so you can see the reference gone? In other words, how to have contains() return false?

ARX
  • 1,040
  • 2
  • 14
  • 20
  • 2
    The reason that snippet always returns `true` is because [`String` literals aren't usually garbage collected](https://stackoverflow.com/questions/15324143/garbage-collection-of-string-literals). – Chai T. Rex Jan 31 '17 at 23:18

1 Answers1

2

As @Chai T.Rex properly mentioned in commentaries, strings is bad example for garbage collection. To see how objects are garbage collected from weak set try this modified version of your code:

    Set<Object> weakSet = Collections.newSetFromMap(new WeakHashMap<>());
    weakSet.add(new Object());
    System.out.println(weakSet.size()); // prints "1"
    while (weakSet.size() > 0)
        System.gc();
    System.out.println(weakSet.size()); // prints "0"

What generally happens here: we add new object into set (weakSet.add(new Object())). But because we do not keep any reference on it, GC will find this object will be removed from set.

Loop on GC is needed, as garbage collecting in this simple example case is not guaranteed.

Andremoniy
  • 34,031
  • 20
  • 135
  • 241
  • Definitely the answer. Thanks for the enlightenment! – ARX Feb 01 '17 at 02:11
  • 1
    …or you change the second line of the original code to `weakSet.add(new String("someKey"));` – Holger Feb 01 '17 at 19:18
  • @Holger, nice idea. But it seems to be little bit less intuitively. – Andremoniy Feb 01 '17 at 19:19
  • Well, it demonstrates why identity based semantics (like instance reachability) doesn’t play nicely with equality semantics (I have a reference to an equivalent object/string, but the whether it is reported to be in the set, depends on how the *other* object was constructed) – Holger Feb 01 '17 at 19:41