Don't store strong references on thread local cache and clean-up request caches properly
^KT-46744 Fixed
This commit is contained in:
+12
-10
@@ -23,9 +23,12 @@ import com.intellij.openapi.components.ServiceManager
|
|||||||
import com.intellij.openapi.util.Computable
|
import com.intellij.openapi.util.Computable
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import com.intellij.psi.PsiJavaModule
|
import com.intellij.psi.PsiJavaModule
|
||||||
|
import java.lang.ref.WeakReference
|
||||||
import java.util.concurrent.CopyOnWriteArrayList
|
import java.util.concurrent.CopyOnWriteArrayList
|
||||||
|
|
||||||
class KotlinBinaryClassCache : Disposable {
|
class KotlinBinaryClassCache : Disposable {
|
||||||
|
private val requestCaches = CopyOnWriteArrayList<WeakReference<RequestCache>>()
|
||||||
|
|
||||||
private class RequestCache {
|
private class RequestCache {
|
||||||
var virtualFile: VirtualFile? = null
|
var virtualFile: VirtualFile? = null
|
||||||
var modificationStamp: Long = 0
|
var modificationStamp: Long = 0
|
||||||
@@ -44,22 +47,21 @@ class KotlinBinaryClassCache : Disposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val cache = object : ThreadLocal<RequestCache>() {
|
private val cache = object : ThreadLocal<RequestCache>() {
|
||||||
private val requestCaches = CopyOnWriteArrayList<RequestCache>()
|
|
||||||
|
|
||||||
override fun initialValue(): RequestCache {
|
override fun initialValue(): RequestCache {
|
||||||
return RequestCache().also { requestCaches.add(it) }
|
return RequestCache().also {
|
||||||
}
|
requestCaches.add(WeakReference(it))
|
||||||
|
|
||||||
override fun remove() {
|
|
||||||
for (cache in requestCaches) {
|
|
||||||
cache.result = null
|
|
||||||
cache.virtualFile = null
|
|
||||||
}
|
}
|
||||||
super.remove()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun dispose() {
|
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
|
// 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
|
// 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
|
// thread-local if they're not removed properly. Each instance would transitively retain VFS resulting in OutOfMemoryError
|
||||||
|
|||||||
Reference in New Issue
Block a user