1

只是试图从 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 吗?但是如果方法调用离开堆栈,那么无论如何都没有可访问的引用。

我想我真正的问题是-“WeakHashMap<>在这里使用实际上很重要”-我认为这是“不,因为影响微不足道”-但是第二个答案不会损害我的知识。

4

1 回答 1

4

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

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

请记住文档

注册的引用对象与其队列之间的关系是片面的。也就是说,队列不会跟踪向其注册的引用。如果已注册的引用本身变得无法访问,那么它将永远不会入队。只要程序对其所指对象感兴趣,程序就有责任使用引用对象来确保对象保持可访问性。

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

WeakHashMap当您对垃圾收集正在进行的时间有强引用时,它会降低性能,因为垃圾收集器必须跟踪遇到的可达WeakReference实例,如果没有遇到和标记它们的引用对象,则将它们清除并入队强可达。这种额外的努力是您必须为允许更早收集密钥和随后的清理而付出的代价,这是删除强引用值所必需的。

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

于 2019-12-12T13:33:49.703 回答