cheptsov / AdvancedExpressionFolding

https://plugins.jetbrains.com/plugin/9320?pr=idea
140 stars 30 forks source link

Memory leak of EditorImpl though AdvancedExpressionFoldingHighlightingComponent.highlighters map #133

Open radomirm-g opened 5 years ago

radomirm-g commented 5 years ago

Android Studio team noticed some heap reports from users show large memory use through AdvancedExpressionFoldingHighlightingComponent class. This memory leak can be observed in both Android Studio and IntelliJ Idea.

Here is relevant part of such report:

 232MB          1   ROOT: Static field: com.intellij.openapi.project.ProjectCoreUtil.theProject
 232MB          1   (root): com.intellij.openapi.project.impl.ProjectImpl
 110MB          1   (disposer-tree): com.intellij.util.containers.DisposableWrapperList$DisposableWrapper
 109MB          1   delegate: com.intellij.advancedExpressionFolding.AdvancedExpressionFoldingHighlightingComponent
 109MB          1   highlighters: java.util.HashMap
 109MB          1   table: java.util.HashMap$Node[]
 109MB         35   []: java.util.HashMap$Node
 109MB         35   key: com.intellij.openapi.editor.impl.EditorImpl

In the example above there are 35 editors in highlighters map for a total of 109MB.

AdvancedExpressionFoldingHighlightingComponent.highlighters stores EditorImpl as keys. The entires are added/removed in fileOpened() (via processEditors())/fileClosed() callbacks.

However, fileClosed() method uses following line to get editors associated with the file: fileEditorManager.getEditors(virtualFile)

At this point, the editor is closed so the call will return empty list. This results in entries never being removed from highlighters map.

One solution might be to use beforeFileClosed() callbacks, though I haven't test if this is enough to fix the leak.

Note the leak is garbage-collected once the project is closed, but it can accumulate over time if the project is never closed and some users rarely close their projects.

There is an easy repro to the bug: just open and close editors (java, kotlin, etc.) and watch in debugger how AdvancedExpressionFoldingHighlightingComponent.highlighters collection only grows.