Is it safe to cache any PSI element if I use PsiModificationTracker.MODIFICATION_COUNT
Hi,
I am curious is it safe to cache project-wide PSI elements if I use PsiModificationTracker.MODIFICATION_COUNT. If I try to cache a PSI element from another file, I get the following error:
... is retaining PSI, causing memory leaks and possible invalid element access.
The code looks like this:
val key = Key<CachedValue<FormPropertyArray<T>?>>("solar.element.array.$requiredPropertyName")
return CachedValuesManager.getCachedValue(this, key) {
val arrayElement = if(requiredPropertyName == name)
FormPropertyArray(this, valueArray, contentsClass)
else
null
CachedValueProvider.Result(
arrayElement,
PsiModificationTracker.MODIFICATION_COUNT
)
}
, where valueArray is a JsonArray (which is causing the problem).
I did a workaround by not caching it directly but reevaluating in FormPropertyArray one more time. I actually cache a lot of project-wide PSI in my project and never experienced any problems while using MODIFICATION_COUNT tracker. I know that this is a memory-hungry approach, but it is still better than searching and traversing multiple JSON files every time to find the required element.
So, do I need to care about this error and stop caching PSI, or can I just ignore that?
There is a link to repository with code, if it helps.
Please sign in to leave a comment.
Hi,
Could you please share the full error stacktrace and message, so we can better understand the case?
Of course, here it is:
Hi,
Indeed, it seems that you capture
valueArray
PSI element besides the element you cache a value for. If you compute a value for a PSI element, you shouldn’t use other PSI elements in the provider code (lambda passed toCachedValuesManager.getCachedValue()
).See the Javadoc of the
com.intellij.psi.util.CachedValue
class, especially “Context-independence” part.