This answer already addresses issues stemming from the use of types with value-based equality in a construct whose behavior depends on the identity of objects, like the reachability.
In short, when you are able to construct new objects with the same equality as the weakly reachable keys, it’s possible to detect the sudden removal of the keys.
However, you can also turn weakly reachable objects back to the strongly reachable state, e.g. by calling the get()
method of a WeakReference
or when iterating over the mappings of a WeakHashMap
.
WeakHashMap<Object, Boolean> map = new WeakHashMap<>();
Object key = new Object();
map.put(key, true);
WeakReference<Object> ref = new WeakReference<>(key);
key = null;
// now, the key object is only weakly reachable
key = ref.get();
// now, the key object might be strongly reachable again
// in that case, this statement will print true
System.out.println(map.get(key));
The construction of an object with a distinct identity and no overridden equals
method via new Object()
ensures that no other reference to the same object nor an equal object can exist. At one point of this code, the object is only weakly reachable, but then, it is made strongly reachable, with a very high likelihood.
It is possible that a garbage collection happens between these points and since all weak references to an object are cleared atomically, you can detect this situation by getting a null
reference from get()
. The likelihood for a garbage collection to happen right at this point is very low, though. That’s why the linked answer uses calls to System.gc()
in-between, to raise the likelihood of the weak references to get cleared.
This is rather a contrived example, but helps addressing you question, “…does that mean that the map will at some point be altered from its original state?”.
If you use equal keys with a different identity or keys which are weakly reachable for some time, the map may get altered at some time, but there is no guaranty that this ever happens. This depends on when the garbage collector will run and actually discover the weak reachability of some objects. But typically, JVMs try to prevent garbage collection until there’s really a demand for it. So an application may run quiet a while without garbage collection at all. Further, if you do poll a mapping regularly, it may even happen, that the gc runs right at that point of time when the key is strongly reachable during the lookup.