diff --git a/core/src/main/java/io/undertow/server/DefaultByteBufferPool.java b/core/src/main/java/io/undertow/server/DefaultByteBufferPool.java index f74a381bf6..5d63625e70 100644 --- a/core/src/main/java/io/undertow/server/DefaultByteBufferPool.java +++ b/core/src/main/java/io/undertow/server/DefaultByteBufferPool.java @@ -26,7 +26,9 @@ import java.nio.ByteBuffer; import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; @@ -39,7 +41,7 @@ */ public class DefaultByteBufferPool implements ByteBufferPool { - private final ThreadLocal threadLocalCache = new ThreadLocal<>(); + private final ThreadLocalCache threadLocalCache = new ThreadLocalCache(); // Access requires synchronization on the threadLocalDataList instance private final List> threadLocalDataList = new ArrayList<>(); private final ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue<>(); @@ -228,6 +230,7 @@ public void close() { local.buffers.clear(); } ref.clear(); + threadLocalCache.remove(local); } threadLocalDataList.clear(); } @@ -332,4 +335,29 @@ protected void finalize() throws Throwable { } } + // This is used instead of Java ThreadLocal class. Unlike in the ThreadLocal class, the remove() method in this + // class can be called by a different thread than the one that initialized the data. + private static class ThreadLocalCache { + + Map localsByThread = new HashMap<>(); + + ThreadLocalData get() { + return localsByThread.get(Thread.currentThread()); + } + + void set(ThreadLocalData threadLocalData) { + localsByThread.put(Thread.currentThread(), threadLocalData); + } + + void remove(ThreadLocalData threadLocalData) { + // Find the entry containing given data instance and remove it from the map. + for (Thread thread: localsByThread.keySet()) { + if (threadLocalData.equals(localsByThread.get(thread))) { + localsByThread.remove(thread, threadLocalData); + break; + } + } + } + } + }