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(); + } + } }