1

Just trying to understand something from GC viewpoint

public Set<Something> returnFromDb(String id) {
   LookupService service = fromSomewhere();
   Map<String,Object> where = new WeakHashMap<>() {}
   where.put("id",id);
   return service.doLookupByKVPair(where); // where doesn't need to be serializable
}

what I understand is that once this method call leaves the stack, there is no reference to where regardless of using HashMap or WeakHashMap - but since weak reference is weakly reachable wouldn't this be GCd faster? But if the method call leaves the stack, then there is no reachable reference anyway.

I guess the real question that I have is - "Would using WeakHashMap<> here actually matters at all" - I think it's a "No, because the impact is insignificant" - but a second answer wouldn't hurt my knowledge.

Naman
  • 27,789
  • 26
  • 218
  • 353
ha9u63a7
  • 6,233
  • 16
  • 73
  • 108
  • 1
    1) any Object that is internally cached by the VM, such as `String` are not really suitable for keys in a WeakHashMap to begin with. 2) you are confusing reachability and scope, which are different things. 3) "Reference processing" (which in GC words is processing Weak/Soft/Phantom/JNI) is _always_ a bigger burden for it compared to plain references. 4) you are passing `where` further down, when `returnFromDb` is done, GC can't simply reclaim that memory. 5) if you are not sure what you are doing (and you seem to not be), stick to a `HashMap` – Eugene Dec 12 '19 at 13:20
  • @Eugene Thanks. Not confusing, but just trying to understand. Also, if these are really burdensome, why have it in Java API at all in the world of microservice and modular application. – ha9u63a7 Dec 13 '19 at 09:41

1 Answers1

4

When you use a statement like where.put("id",id); you’re associating a value with a String instance created from a literal, permanently referenced by the code containing it. So the weak semantic of the association is pointless, as long as the code is reachable, this specific key object will never get garbage collected.

When the entire WeakHashMap becomes unreachable, the weak nature of the references has no impact on the garbage collection, as unreachable objects have in general. As discussed in this answer, the garbage collection performance mainly depends on the reachable objects, not the unreachable ones.

Keep in mind the documentation:

The relationship between a registered reference object and its queue is one-sided. That is, a queue does not keep track of the references that are registered with it. If a registered reference becomes unreachable itself, then it will never be enqueued. It is the responsibility of the program using reference objects to ensure that the objects remain reachable for as long as the program is interested in their referents.

In other words, a WeakReference has no impact when it is unreachable, as it will be treated like any other garbage, i.e. not treated at all.

When you have a strong reference to a WeakHashMap while a garbage collection is in progress, it will reduce the performance, as the garbage collector has to keep track of the encountered reachable WeakReference instances, to clear and enqueue them if their referent has not been encountered and marked as strongly reachable. This additional effort is the price you have to pay for allowing the earlier collection of the keys and the subsequent cleanup, which is needed to remove the strongly referenced value.

As said, when, like in your example, the key will never become garbage collected, this additional effort is wasted. But if no garbage collection happens while the WeakHashMap is used, there will be no impact, as said, as the collection of an entire object graph happens at once, regardless of what kind of objects are in the garbage.

Holger
  • 285,553
  • 42
  • 434
  • 765