我们有使用spring-cloud-netflix-core库的情况,其中描述了here。我认为问题在于CachingSpringLoadBalancerFactory
使用ConcurrentReferenceHashMap
报告here的方式。
还有ConcurrentReferenceHashMap
(使用软引用)的文档:
引用的使用意味着无法保证放入地图的项目随后可用。垃圾收集器可能随时丢弃引用,因此可能看起来未知线程正在静默删除条目。
现在我的问题是:
1.我的理解是否正确?
// Original code is in CachingSpringLoadBalancerFactory in spring-cloud-netflix-core
// cache is a field of type ConcurrentReferenceHashMap
if (this.cache.containsKey(clientName)) {
return this.cache.get(clientName); // This can be null, right?
}
2。无论如何都要为它编写一个测试用例。我们设法在内存有限的独立应用程序中重现一次(-Xmx50m
)。但是,我们如何编写单元测试来涵盖这种情况?
答案 0 :(得分:0)
关于你的问题,是的,这是对的。通常,这是WeakHashMap
的变体,如文档中所述。
WeakHashMap
的JavaDoc说:
" WeakHashMap
类的行为部分取决于垃圾收集器的操作,因此几个熟悉的(虽然不是必需的)Map
不变量不适用于此类。由于垃圾收集器可能随时丢弃密钥,因此WeakHashMap
可能表现为未知线程正在静默删除条目。特别是,即使您在WeakHashMap
实例上进行同步并且不调用其任何mutator方法,size
方法也可能会随着时间的推移返回较小的值,isEmpty
方法返回false
然后true
,containsKey
方法返回true
,然后false
返回给定密钥,get
方法返回null
返回给定键的值,但稍后返回put
,null
方法返回remove
,false
方法返回getReference()
以获取键以前似乎是在地图中,并且对于密钥集,值集合和条目集的连续检查产生了相继较少数量的元素。"
由于这种行为,很难进行测试。如果要测试某些不变量,可以使用地图的release()
方法和相应元素的select
case
when mod(round(dbms_random.value(1,100)),2) = 0 then dbms_output.put_line('M');
when mod(round(dbms_random.value(1,100)),2) = 1 then dbms_output.put_line('W');
end
from dual
方法来模拟清除。
答案 1 :(得分:0)
根据我对文档意图的理解,这应该取决于您的键和值是否在地图之外被强烈引用。您不知道是不是这种情况。
但是,地图实现(直到现在)似乎并未实际使用对单个键/值的软/弱引用,而是管理内部的非强引用地图条目,然后根据引用类型将其设为空忽略gc(弱引用)或低内存(软引用),而不考虑键/值的强可达性。修复之前的解决方法(或我的错误报告无效;-))包括使用具有相同名称的Hibernate / Hibernate验证器类(Doug Lee的公共领域实现,而该实现从未以某种方式包含在JDK中)或Guava的MapMaker.weakKeys( ).weakValues(),以防您真的不需要软引用。
请参见https://github.com/spring-projects/spring-framework/issues/24253