FIR IDE: generate heap dump on memory leak in memory leak test
This commit is contained in:
+26
-2
@@ -7,7 +7,9 @@ package org.jetbrains.kotlin.idea.frontend.api.symbols
|
|||||||
|
|
||||||
import com.intellij.openapi.components.service
|
import com.intellij.openapi.components.service
|
||||||
import com.intellij.openapi.util.io.FileUtil
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
|
import com.sun.management.HotSpotDiagnosticMXBean
|
||||||
import junit.framework.Assert
|
import junit.framework.Assert
|
||||||
|
import org.jetbrains.kotlin.idea.caches.project.LibraryModificationTracker
|
||||||
import org.jetbrains.kotlin.idea.executeOnPooledThreadInReadAction
|
import org.jetbrains.kotlin.idea.executeOnPooledThreadInReadAction
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.trackers.KotlinFirOutOfBlockModificationTrackerFactory
|
import org.jetbrains.kotlin.idea.fir.low.level.api.trackers.KotlinFirOutOfBlockModificationTrackerFactory
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.InvalidWayOfUsingAnalysisSession
|
import org.jetbrains.kotlin.idea.frontend.api.InvalidWayOfUsingAnalysisSession
|
||||||
@@ -21,7 +23,14 @@ import org.jetbrains.kotlin.psi.KtDeclaration
|
|||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType
|
import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType
|
||||||
import org.jetbrains.kotlin.trackers.KotlinOutOfBlockModificationTrackerFactory
|
import org.jetbrains.kotlin.trackers.KotlinOutOfBlockModificationTrackerFactory
|
||||||
|
import sun.management.HotSpotDiagnostic
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.lang.management.ManagementFactory
|
||||||
|
import java.nio.file.Path
|
||||||
|
import java.nio.file.Paths
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.*
|
||||||
|
import kotlin.io.path.absolute
|
||||||
|
|
||||||
abstract class AbstractMemoryLeakInSymbolsTest : KotlinLightCodeInsightFixtureTestCase() {
|
abstract class AbstractMemoryLeakInSymbolsTest : KotlinLightCodeInsightFixtureTestCase() {
|
||||||
override fun isFirPlugin() = true
|
override fun isFirPlugin() = true
|
||||||
@@ -42,8 +51,11 @@ abstract class AbstractMemoryLeakInSymbolsTest : KotlinLightCodeInsightFixtureTe
|
|||||||
symbols.map { it.hasNoFirElementLeak() }.filterIsInstance<LeakCheckResult.Leak>()
|
symbols.map { it.hasNoFirElementLeak() }.filterIsInstance<LeakCheckResult.Leak>()
|
||||||
}
|
}
|
||||||
if (leakedSymbols.isNotEmpty()) {
|
if (leakedSymbols.isNotEmpty()) {
|
||||||
|
val memoryDumpPath = dumpHeap()
|
||||||
Assert.fail(
|
Assert.fail(
|
||||||
"""The following symbols leaked (${leakedSymbols.size}/${symbols.size})
|
"""Some symbols leaked (${leakedSymbols.size}/${symbols.size})
|
||||||
|
Memory dump is $memoryDumpPath
|
||||||
|
Symbols:
|
||||||
${leakedSymbols.joinToString(separator = "\n") { it.symbol }}
|
${leakedSymbols.joinToString(separator = "\n") { it.symbol }}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
)
|
)
|
||||||
@@ -53,6 +65,7 @@ abstract class AbstractMemoryLeakInSymbolsTest : KotlinLightCodeInsightFixtureTe
|
|||||||
@OptIn(InvalidWayOfUsingAnalysisSession::class)
|
@OptIn(InvalidWayOfUsingAnalysisSession::class)
|
||||||
private fun invalidateAllCaches(ktFile: KtFile) {
|
private fun invalidateAllCaches(ktFile: KtFile) {
|
||||||
(project.service<KotlinOutOfBlockModificationTrackerFactory>() as KotlinFirOutOfBlockModificationTrackerFactory).incrementModificationsCount()
|
(project.service<KotlinOutOfBlockModificationTrackerFactory>() as KotlinFirOutOfBlockModificationTrackerFactory).incrementModificationsCount()
|
||||||
|
// project.service<LibraryModificationTracker>().incModificationCount()
|
||||||
(project.service<KtAnalysisSessionProvider>() as KtFirAnalysisSessionProvider).clearCaches()
|
(project.service<KtAnalysisSessionProvider>() as KtFirAnalysisSessionProvider).clearCaches()
|
||||||
executeOnPooledThreadInReadAction { analyze(ktFile) {} }
|
executeOnPooledThreadInReadAction { analyze(ktFile) {} }
|
||||||
}
|
}
|
||||||
@@ -67,5 +80,16 @@ abstract class AbstractMemoryLeakInSymbolsTest : KotlinLightCodeInsightFixtureTe
|
|||||||
object NoLeak : LeakCheckResult()
|
object NoLeak : LeakCheckResult()
|
||||||
data class Leak(val symbol: String) : LeakCheckResult()
|
data class Leak(val symbol: String) : LeakCheckResult()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
private fun dumpHeap(): Path {
|
||||||
|
val fileNameSuffix = SimpleDateFormat("yyMMddHHmmss").format(Date())
|
||||||
|
val path = Paths.get(basePath).resolve("memoryLeakDump_${fileNameSuffix}.hprof")
|
||||||
|
val server = ManagementFactory.getPlatformMBeanServer()
|
||||||
|
ManagementFactory.newPlatformMXBeanProxy(
|
||||||
|
server,
|
||||||
|
"com.sun.management:type=HotSpotDiagnostic",
|
||||||
|
HotSpotDiagnosticMXBean::class.java
|
||||||
|
).dumpHeap(path.toString(), true)
|
||||||
|
return path.toAbsolutePath()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user