From 2b290fd274ce901213b5042ab7afac393bbd2d0c Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 16 Sep 2016 15:44:39 +0200 Subject: [PATCH] IDEA-161261 LowMemoryWatcher sporadically fails with ConcurrentModificationException --- .../intellij/openapi/util/LowMemoryWatcher.java | 6 ++---- .../openapi/util/LowMemoryWatcherManager.java | 16 +++++++++++++++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/platform/util/src/com/intellij/openapi/util/LowMemoryWatcher.java b/platform/util/src/com/intellij/openapi/util/LowMemoryWatcher.java index 4edf039b7545..d5d8d2ed2814 100644 --- a/platform/util/src/com/intellij/openapi/util/LowMemoryWatcher.java +++ b/platform/util/src/com/intellij/openapi/util/LowMemoryWatcher.java @@ -21,8 +21,6 @@ import com.intellij.util.containers.WeakList; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; -import java.util.List; - /** * @author Eugene Zhuravlev * Date: Aug 24, 2010 @@ -30,12 +28,12 @@ import java.util.List; public class LowMemoryWatcher { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.util.LowMemoryWatcher"); - private static final List ourListeners = new WeakList(); + private static final WeakList ourListeners = new WeakList(); private final Runnable myRunnable; static void onLowMemorySignalReceived() { LOG.info("Low memory signal received."); - for (Runnable watcher : ourListeners) { + for (Runnable watcher : ourListeners.toStrongList()) { try { watcher.run(); } diff --git a/platform/util/src/com/intellij/openapi/util/LowMemoryWatcherManager.java b/platform/util/src/com/intellij/openapi/util/LowMemoryWatcherManager.java index bcb71d47fa32..d38d02df4631 100644 --- a/platform/util/src/com/intellij/openapi/util/LowMemoryWatcherManager.java +++ b/platform/util/src/com/intellij/openapi/util/LowMemoryWatcherManager.java @@ -31,6 +31,7 @@ import java.lang.management.MemoryPoolMXBean; import java.lang.management.MemoryType; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicBoolean; public class LowMemoryWatcherManager implements Disposable { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.util.LowMemoryWatcherManager"); @@ -38,6 +39,7 @@ public class LowMemoryWatcherManager implements Disposable { private static final long MEM_THRESHOLD = 5 /*MB*/ * 1024 * 1024; private Future mySubmitted; // guarded by ourJanitor + private final AtomicBoolean myProcessing = new AtomicBoolean(); private final Runnable myJanitor = new Runnable() { @Override public void run() { @@ -75,7 +77,7 @@ public class LowMemoryWatcherManager implements Disposable { if (MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED.equals(notification.getType()) || MemoryNotificationInfo.MEMORY_COLLECTION_THRESHOLD_EXCEEDED.equals(notification.getType())) { if (Registry.is("low.memory.watcher.sync", true)) { - myJanitor.run(); + handleEventImmediately(); return; } @@ -87,6 +89,18 @@ public class LowMemoryWatcherManager implements Disposable { } } }; + + private void handleEventImmediately() { + if (myProcessing.compareAndSet(false, true)) { + try { + myJanitor.run(); + } + finally { + myProcessing.set(false); + } + } + } + private final NotNullLazyValue myExecutor = new NotNullLazyValue() { @NotNull @Override