Java - 应用程序中使用的 HashMap 和 WeakHashMap 引用

Java - HashMap and WeakHashMap references used in Application

只是想从 GC 的角度理解一些东西

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
}

我的理解是,一旦这个方法调用离开堆栈,就没有对 where 的引用,无论使用 HashMap 还是 WeakHashMap - 但由于弱引用是弱可达的这不是 GCd 更快吗?但是如果方法调用离开了堆栈,那么无论如何都没有可达的引用。

我想我真正的问题是 - "Would using WeakHashMap<> here actually matters at all" - 我认为这是一个 "No, because the impact is insignificant" - 但第二个答案不会损害我的知识。

当你使用像 where.put("id",id); 这样的语句时,你将一个值与一个 String 实例相关联,该实例是从文字创建的,由包含它的代码永久引用。所以关联的弱语义是没有意义的,只要代码可达,这个特定的关键对象永远不会被垃圾收集。

当整个 WeakHashMap 变得不可访问时,引用的弱性质对垃圾回收没有影响,因为不可访问的对象通常具有。正如中所讨论的,垃圾回收性能主要取决于可达对象,而不是不可达对象。

牢记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.

换句话说,WeakReference 在无法访问时没有任何影响,因为它将像其他任何垃圾一样处理,即根本不处理。

如果在垃圾收集过程中对 WeakHashMap 有强引用,它将 降低 性能,因为垃圾收集器必须跟踪遇到的可达 WeakReference 个实例,如果没有遇到它们的指代物并标记为强可达,则清除它们并将它们排入队列。这种额外的努力是您为允许更早收集键和随后的清理而必须付出的代价,这是删除强引用值所必需的。

如前所述,当密钥永远不会像您的示例那样被垃圾收集时,这种额外的努力就白费了。但是,如果在使用 WeakHashMap 时没有发生垃圾收集,则不会产生任何影响,因为整个对象图的收集会立即发生,而不管垃圾中的对象是什么类型。