diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index c450a1d4fc89ff6a47ffecfe5d6fd2c67f2ffdee..607f7644b3e956d1924a5ad23854c9fcd19e21d7 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -28,6 +28,7 @@ import com.android.inputmethod.latin.makedict.FormatSpec;
 import com.android.inputmethod.latin.makedict.FusionDictionary.DictionaryOptions;
 import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
 import com.android.inputmethod.latin.makedict.WordProperty;
+import com.android.inputmethod.latin.personalization.PersonalizationHelper;
 import com.android.inputmethod.latin.settings.NativeSuggestOptions;
 import com.android.inputmethod.latin.utils.CollectionUtils;
 import com.android.inputmethod.latin.utils.FileUtils;
@@ -508,7 +509,9 @@ public final class BinaryDictionary extends Dictionary {
      */
     @UsedForTesting
     public static int setCurrentTimeForTest(final int currentTime) {
-        return setCurrentTimeForTestNative(currentTime);
+        final int currentNativeTimestamp = setCurrentTimeForTestNative(currentTime);
+        PersonalizationHelper.currentTimeChangedForTesting(currentNativeTimestamp);
+        return currentNativeTimestamp;
     }
 
     @UsedForTesting
diff --git a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
index 8c358cd50cf568e2f67619e60b0e8d4b04b06026..ca8a72c9d72f5cfca2a45ad831f88d43d80b1501 100644
--- a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
+++ b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
@@ -163,7 +163,7 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB
         clearAndFlushDictionary();
     }
 
-    /* package */ void decayIfNeeded() {
+    /* package */ void runGCIfRequired() {
         runGCIfRequired(false /* mindsBlockByGC */);
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java b/java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java
index e9ca662e7a356bcfad2ec6ee04e7b88193a3a17c..de2744f29220f8aa1a3b31f5629b4398a0ea6e3c 100644
--- a/java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java
+++ b/java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java
@@ -43,7 +43,7 @@ public class DictionaryDecayBroadcastReciever extends BroadcastReceiver {
     /**
      * Interval to update for decaying dictionaries.
      */
-    private static final long DICTIONARY_DECAY_INTERVAL = TimeUnit.MINUTES.toMillis(60);
+    /* package */ static final long DICTIONARY_DECAY_INTERVAL = TimeUnit.MINUTES.toMillis(60);
 
     public static void setUpIntervalAlarmForDictionaryDecaying(Context context) {
         AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
@@ -60,7 +60,7 @@ public class DictionaryDecayBroadcastReciever extends BroadcastReceiver {
     public void onReceive(final Context context, final Intent intent) {
         final String action = intent.getAction();
         if (action.equals(DICTIONARY_DECAY_INTENT_ACTION)) {
-            PersonalizationHelper.tryDecayingAllOpeningUserHistoryDictionary();
+            PersonalizationHelper.runGCOnAllOpenedUserHistoryDictionaries();
         }
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java
index 5ae2fb6f8add270e9a8cc20fe4f272f29c0e1da3..385b525b6d7ffb35e99813ae764d9ee20f8a6399 100644
--- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java
+++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java
@@ -16,6 +16,7 @@
 
 package com.android.inputmethod.latin.personalization;
 
+import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.latin.utils.CollectionUtils;
 import com.android.inputmethod.latin.utils.FileUtils;
 
@@ -27,6 +28,7 @@ import java.io.FilenameFilter;
 import java.lang.ref.SoftReference;
 import java.util.Locale;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
 
 public class PersonalizationHelper {
     private static final String TAG = PersonalizationHelper.class.getSimpleName();
@@ -59,14 +61,35 @@ public class PersonalizationHelper {
         }
     }
 
-    public static void tryDecayingAllOpeningUserHistoryDictionary() {
-        for (final ConcurrentHashMap.Entry<String, SoftReference<UserHistoryDictionary>> entry
-                : sLangUserHistoryDictCache.entrySet()) {
-            if (entry.getValue() != null) {
-                final UserHistoryDictionary dict = entry.getValue().get();
-                if (dict != null) {
-                    dict.decayIfNeeded();
-                }
+    private static int sCurrentTimestampForTesting = 0;
+    public static void currentTimeChangedForTesting(final int currentTimestamp) {
+        if (TimeUnit.MILLISECONDS.toSeconds(
+                DictionaryDecayBroadcastReciever.DICTIONARY_DECAY_INTERVAL)
+                        < currentTimestamp - sCurrentTimestampForTesting) {
+            // TODO: Run GC for both PersonalizationDictionary and UserHistoryDictionary.
+            runGCOnAllOpenedUserHistoryDictionaries();
+        }
+    }
+
+    public static void runGCOnAllOpenedUserHistoryDictionaries() {
+        runGCOnAllDictionariesIfRequired(sLangUserHistoryDictCache);
+    }
+
+    @UsedForTesting
+    public static void runGCOnAllOpenedPersonalizationDictionaries() {
+        runGCOnAllDictionariesIfRequired(sLangPersonalizationDictCache);
+    }
+
+    private static <T extends DecayingExpandableBinaryDictionaryBase>
+            void runGCOnAllDictionariesIfRequired(
+                    final ConcurrentHashMap<String, SoftReference<T>> dictionaryMap) {
+        for (final ConcurrentHashMap.Entry<String, SoftReference<T>> entry
+                : dictionaryMap.entrySet()) {
+            final DecayingExpandableBinaryDictionaryBase dict = entry.getValue().get();
+            if (dict != null) {
+                dict.runGCIfRequired();
+            } else {
+                dictionaryMap.remove(entry.getKey());
             }
         }
     }
diff --git a/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java
index b1239f0af810b31a78ee9cb43c9441038defb3fa..6ace2de4f924b481900e97141aa4f033b13e2269 100644
--- a/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java
@@ -267,13 +267,13 @@ public class UserHistoryDictionaryTests extends AndroidTestCase {
             assertTrue(dict.isInUnderlyingBinaryDictionaryForTests(word));
         }
         forcePassingShortTime();
-        dict.decayIfNeeded();
+        dict.runGCIfRequired();
         dict.waitAllTasksForTests();
         for (final String word : words) {
             assertTrue(dict.isInUnderlyingBinaryDictionaryForTests(word));
         }
         forcePassingLongTime();
-        dict.decayIfNeeded();
+        dict.runGCIfRequired();
         dict.waitAllTasksForTests();
         for (final String word : words) {
             assertFalse(dict.isInUnderlyingBinaryDictionaryForTests(word));