From 3fd4de38092cf25cf7030c75993d9d5228e48a7b Mon Sep 17 00:00:00 2001 From: Petr Kudriavtsev Date: Tue, 26 Mar 2024 16:51:12 +0100 Subject: [PATCH] [clion] fixed CPP-38152/Project-leak-in-CLion-Trunk-General-Tests-on-Win-11 LeakHunter should trigger erasing of expired elements from WeakHashMaps before checking them to avoid false positives. https://jetbrains.team/p/ij/reviews/130067/files GitOrigin-RevId: abda6fb6bc88ba3f104d25bddf9fc18405c9a4d8 --- .../intellij/util/ref/DebugReflectionUtil.java | 4 ++++ .../testFramework/common/src/LeakHunter.java | 2 ++ .../util/containers/RefValueHashMapUtil.java | 17 ++++++++++++++++- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/platform/core-impl/src/com/intellij/util/ref/DebugReflectionUtil.java b/platform/core-impl/src/com/intellij/util/ref/DebugReflectionUtil.java index e4604fd17c07..4284ec93bfef 100644 --- a/platform/core-impl/src/com/intellij/util/ref/DebugReflectionUtil.java +++ b/platform/core-impl/src/com/intellij/util/ref/DebugReflectionUtil.java @@ -10,6 +10,7 @@ import com.intellij.util.ReflectionUtil; import com.intellij.util.containers.CollectionFactory; import com.intellij.util.containers.FList; import com.intellij.util.containers.HashingStrategy; +import com.intellij.util.containers.RefValueHashMapUtil; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; import org.jetbrains.annotations.NotNull; @@ -157,6 +158,9 @@ public final class DebugReflectionUtil { @NotNull BackLink backLink, @NotNull Predicate shouldExamineValue) { Class rootClass = root.getClass(); + if (root instanceof Map) { + RefValueHashMapUtil.expungeStaleEntries((Map)root); + } for (Field field : getAllFields(rootClass)) { String fieldName = field.getName(); // do not follow weak/soft refs diff --git a/platform/testFramework/common/src/LeakHunter.java b/platform/testFramework/common/src/LeakHunter.java index f2317129293a..1c673751b622 100644 --- a/platform/testFramework/common/src/LeakHunter.java +++ b/platform/testFramework/common/src/LeakHunter.java @@ -85,6 +85,8 @@ public final class LeakHunter { UIUtil.pump(); } PersistentEnumeratorCache.clearCacheForTests(); + //noinspection CallToSystemGC + System.gc(); Runnable runnable = () -> { try (AccessToken ignored = ProhibitAWTEvents.start("checking for leaks")) { DebugReflectionUtil.walkObjects(10000, rootsSupplier.get(), suspectClass, __ -> true, (leaked, backLink) -> { diff --git a/platform/util/base/src/com/intellij/util/containers/RefValueHashMapUtil.java b/platform/util/base/src/com/intellij/util/containers/RefValueHashMapUtil.java index 33c364a62b50..e46871001dac 100644 --- a/platform/util/base/src/com/intellij/util/containers/RefValueHashMapUtil.java +++ b/platform/util/base/src/com/intellij/util/containers/RefValueHashMapUtil.java @@ -2,9 +2,13 @@ package com.intellij.util.containers; import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; -final class RefValueHashMapUtil { +import java.util.Map; + +@ApiStatus.Internal +public final class RefValueHashMapUtil { public static @NotNull IncorrectOperationException pointlessContainsKey() { return new IncorrectOperationException("containsKey() makes no sense for weak/soft map because GC can clear the value any moment now"); } @@ -12,4 +16,15 @@ final class RefValueHashMapUtil { public static @NotNull IncorrectOperationException pointlessContainsValue() { return new IncorrectOperationException("containsValue() makes no sense for weak/soft map because GC can clear the key any moment now"); } + + public static void expungeStaleEntries(@NotNull Map map) { + if (map instanceof com.intellij.util.containers.WeakHashMap) { + ((com.intellij.util.containers.WeakHashMap)map).processQueue(); + } + else if (map instanceof java.util.WeakHashMap) { + // Calling the size() method forces cleansing of the WeakHashMap + //noinspection ResultOfMethodCallIgnored + map.size(); + } + } }