[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
This commit is contained in:
Petr Kudriavtsev
2024-03-26 16:51:12 +01:00
committed by intellij-monorepo-bot
parent 0249876623
commit 3fd4de3809
3 changed files with 22 additions and 1 deletions

View File

@@ -10,6 +10,7 @@ import com.intellij.util.ReflectionUtil;
import com.intellij.util.containers.CollectionFactory; import com.intellij.util.containers.CollectionFactory;
import com.intellij.util.containers.FList; import com.intellij.util.containers.FList;
import com.intellij.util.containers.HashingStrategy; 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.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet; import it.unimi.dsi.fastutil.ints.IntSet;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -157,6 +158,9 @@ public final class DebugReflectionUtil {
@NotNull BackLink<?> backLink, @NotNull BackLink<?> backLink,
@NotNull Predicate<Object> shouldExamineValue) { @NotNull Predicate<Object> shouldExamineValue) {
Class<?> rootClass = root.getClass(); Class<?> rootClass = root.getClass();
if (root instanceof Map) {
RefValueHashMapUtil.expungeStaleEntries((Map<?, ?>)root);
}
for (Field field : getAllFields(rootClass)) { for (Field field : getAllFields(rootClass)) {
String fieldName = field.getName(); String fieldName = field.getName();
// do not follow weak/soft refs // do not follow weak/soft refs

View File

@@ -85,6 +85,8 @@ public final class LeakHunter {
UIUtil.pump(); UIUtil.pump();
} }
PersistentEnumeratorCache.clearCacheForTests(); PersistentEnumeratorCache.clearCacheForTests();
//noinspection CallToSystemGC
System.gc();
Runnable runnable = () -> { Runnable runnable = () -> {
try (AccessToken ignored = ProhibitAWTEvents.start("checking for leaks")) { try (AccessToken ignored = ProhibitAWTEvents.start("checking for leaks")) {
DebugReflectionUtil.walkObjects(10000, rootsSupplier.get(), suspectClass, __ -> true, (leaked, backLink) -> { DebugReflectionUtil.walkObjects(10000, rootsSupplier.get(), suspectClass, __ -> true, (leaked, backLink) -> {

View File

@@ -2,9 +2,13 @@
package com.intellij.util.containers; package com.intellij.util.containers;
import com.intellij.util.IncorrectOperationException; import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
final class RefValueHashMapUtil { import java.util.Map;
@ApiStatus.Internal
public final class RefValueHashMapUtil {
public static @NotNull IncorrectOperationException pointlessContainsKey() { 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"); 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() { 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"); 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();
}
}
} }