diff --git a/src/main/java/org/apache/ibatis/cache/decorators/FifoCache.java b/src/main/java/org/apache/ibatis/cache/decorators/FifoCache.java index 9fc9c2f0f4c..61fb143f471 100644 --- a/src/main/java/org/apache/ibatis/cache/decorators/FifoCache.java +++ b/src/main/java/org/apache/ibatis/cache/decorators/FifoCache.java @@ -1,5 +1,5 @@ /* - * Copyright 2009-2023 the original author or authors. + * Copyright 2009-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -49,6 +49,7 @@ public int getSize() { public void setSize(int size) { this.size = size; + resizeKeyList(); } @Override @@ -82,4 +83,11 @@ private void cycleKeyList(Object key) { } } + private void resizeKeyList() { + while (keyList.size() > size) { + Object oldestKey = keyList.removeFirst(); + delegate.removeObject(oldestKey); + } + } + } diff --git a/src/main/java/org/apache/ibatis/cache/decorators/SoftCache.java b/src/main/java/org/apache/ibatis/cache/decorators/SoftCache.java index 271bbe4a224..20d832959fd 100644 --- a/src/main/java/org/apache/ibatis/cache/decorators/SoftCache.java +++ b/src/main/java/org/apache/ibatis/cache/decorators/SoftCache.java @@ -57,6 +57,7 @@ public int getSize() { public void setSize(int size) { this.numberOfHardLinks = size; + resizeHardLinks(); } @Override @@ -78,6 +79,7 @@ public Object getObject(Object key) { // See #586 (and #335) modifications need more than a read lock lock.lock(); try { + hardLinksToAvoidGarbageCollection.remove(result); hardLinksToAvoidGarbageCollection.addFirst(result); if (hardLinksToAvoidGarbageCollection.size() > numberOfHardLinks) { hardLinksToAvoidGarbageCollection.removeLast(); @@ -117,6 +119,17 @@ private void removeGarbageCollectedItems() { } } + private void resizeHardLinks() { + lock.lock(); + try { + while (hardLinksToAvoidGarbageCollection.size() > numberOfHardLinks) { + hardLinksToAvoidGarbageCollection.removeLast(); + } + } finally { + lock.unlock(); + } + } + private static class SoftEntry extends SoftReference { private final Object key; diff --git a/src/main/java/org/apache/ibatis/cache/decorators/WeakCache.java b/src/main/java/org/apache/ibatis/cache/decorators/WeakCache.java index 772cdbafbed..02f05b803f4 100644 --- a/src/main/java/org/apache/ibatis/cache/decorators/WeakCache.java +++ b/src/main/java/org/apache/ibatis/cache/decorators/WeakCache.java @@ -57,6 +57,7 @@ public int getSize() { public void setSize(int size) { this.numberOfHardLinks = size; + resizeHardLinks(); } @Override @@ -77,6 +78,7 @@ public Object getObject(Object key) { } else { lock.lock(); try { + hardLinksToAvoidGarbageCollection.remove(result); hardLinksToAvoidGarbageCollection.addFirst(result); if (hardLinksToAvoidGarbageCollection.size() > numberOfHardLinks) { hardLinksToAvoidGarbageCollection.removeLast(); @@ -116,6 +118,17 @@ private void removeGarbageCollectedItems() { } } + private void resizeHardLinks() { + lock.lock(); + try { + while (hardLinksToAvoidGarbageCollection.size() > numberOfHardLinks) { + hardLinksToAvoidGarbageCollection.removeLast(); + } + } finally { + lock.unlock(); + } + } + private static class WeakEntry extends WeakReference { private final Object key; diff --git a/src/test/java/org/apache/ibatis/cache/FifoCacheTest.java b/src/test/java/org/apache/ibatis/cache/FifoCacheTest.java index c492aef615d..b6cd42261d8 100644 --- a/src/test/java/org/apache/ibatis/cache/FifoCacheTest.java +++ b/src/test/java/org/apache/ibatis/cache/FifoCacheTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2009-2023 the original author or authors. + * Copyright 2009-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -72,4 +72,19 @@ void shouldRiseConflictInBeyondFiveEntries() { assertNotNull(cache.getObject(0)); } + @Test + void shouldResizeKeyList() { + FifoCache cache = new FifoCache(new PerpetualCache("default")); + cache.setSize(5); + for (int i = 0; i < 5; i++) { + cache.putObject(i, i); + } + cache.setSize(3); + assertNull(cache.getObject(0)); + assertNull(cache.getObject(1)); + assertNotNull(cache.getObject(2)); + assertNotNull(cache.getObject(3)); + assertNotNull(cache.getObject(4)); + } + }