diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/KotlinBinaryClassCache.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/KotlinBinaryClassCache.kt index 49ff93c8e88..c43b2826ad0 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/KotlinBinaryClassCache.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/KotlinBinaryClassCache.kt @@ -23,9 +23,12 @@ import com.intellij.openapi.components.ServiceManager import com.intellij.openapi.util.Computable import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.PsiJavaModule +import java.lang.ref.WeakReference import java.util.concurrent.CopyOnWriteArrayList class KotlinBinaryClassCache : Disposable { + private val requestCaches = CopyOnWriteArrayList>() + private class RequestCache { var virtualFile: VirtualFile? = null var modificationStamp: Long = 0 @@ -44,22 +47,21 @@ class KotlinBinaryClassCache : Disposable { } private val cache = object : ThreadLocal() { - private val requestCaches = CopyOnWriteArrayList() - override fun initialValue(): RequestCache { - return RequestCache().also { requestCaches.add(it) } - } - - override fun remove() { - for (cache in requestCaches) { - cache.result = null - cache.virtualFile = null + return RequestCache().also { + requestCaches.add(WeakReference(it)) } - super.remove() } } override fun dispose() { + for (cache in requestCaches) { + cache.get()?.run { + result = null + virtualFile = null + } + } + requestCaches.clear() // This is only relevant for tests. We create a new instance of Application for each test, and so a new instance of this service is // also created for each test. However all tests share the same event dispatch thread, which would collect all instances of this // thread-local if they're not removed properly. Each instance would transitively retain VFS resulting in OutOfMemoryError