我正在使用
ConcurrentHashMap
来缓存一些短期数据。即缓存中的条目不多,但经常发生插入和删除。问题是,当在负载下工作时,GC 不会删除 java.util.concurrent.ConcurrentHashMap$Node
并且它们会累积在堆中。即使负载结束后,它们也没有被清理。
我的单例缓存管理器
@Component
public class ZipkinTraceCacheManager {
private final Map<String, ZipkinTraceCache> threadCaches = new ConcurrentHashMap<>();
public ZipkinTraceCache getCache(String mainSpanId) {
return threadCaches.get(mainSpanId);
}
public void removeCache(String mainSpanId) {
threadCaches.remove(mainSpanId);
}
public String initNewCache(Span mainSpan) {
ZipkinTraceCache zipkinTraceCache = new ZipkinTraceCache();
zipkinTraceCache.setMainSpan(mainSpan);
String mainSpanId = mainSpan.context().spanId();
threadCaches.put(mainSpanId, zipkinTraceCache);
return mainSpanId;
}
}
负载结束后,所有
java.util.concurrent.ConcurrentHashMap$Node
实例仍处于活动状态
我需要做什么才能停止积累这些参考文献?
你使用的是Spring还是spring-boot? @Component 具有单例的默认范围,这意味着:-
当 Spring IoC 容器启动时,它会创建一个单例 bean 的实例,并且该实例在应用程序上下文的整个生命周期内都存在。因此,任何类变量(例如示例中的 threadCache)也会被实例化,并在应用程序上下文的整个生命周期内有效。当包含 threadCache 的单例 bean 符合垃圾回收条件时,将发生 threadCache 的垃圾回收。当应用程序上下文关闭或整个应用程序关闭,并且没有其他对单例 bean 的引用时,通常会发生这种情况。
ConcurrentHashMap.Node 在堆中累积而没有被垃圾收集器 (GC) 清理可能是由于一些潜在原因造成的,通常与引用或内存保留有关。以下是一些常见场景以及调查并可能解决问题的步骤: