diff --git a/common/src/main/java/io/netty/util/Recycler.java b/common/src/main/java/io/netty/util/Recycler.java index d872e75f33..4bd3f124e1 100644 --- a/common/src/main/java/io/netty/util/Recycler.java +++ b/common/src/main/java/io/netty/util/Recycler.java @@ -223,7 +223,7 @@ public abstract class Recycler { private WeakOrderQueue next; private final WeakReference owner; private final int id = ID_GENERATOR.getAndIncrement(); - private final Stack stack; + private final AtomicInteger availableSharedCapacity; WeakOrderQueue(Stack stack, Thread thread) { head = tail = new Link(); @@ -232,19 +232,42 @@ public abstract class Recycler { next = stack.head; stack.head = this; } - this.stack = stack; + + // Its important that we not store the Stack itself in the WeakOrderQueue as the Stack also is used in + // the WeakHashMap as key. So just store the enclosed AtomicInteger which should allow to have the + // Stack itself GCed. + availableSharedCapacity = stack.availableSharedCapacity; + // We allocated a Link so reserve the space - boolean reserved = stack.reserveSpace(LINK_CAPACITY); + boolean reserved = reserveSpace(LINK_CAPACITY); assert reserved; } + private boolean reserveSpace(int space) { + assert space >= 0; + for (;;) { + int available = availableSharedCapacity.get(); + if (available < space) { + return false; + } + if (availableSharedCapacity.compareAndSet(available, available - space)) { + return true; + } + } + } + + private void reclaimSpace(int space) { + assert space >= 0; + availableSharedCapacity.addAndGet(space); + } + void add(DefaultHandle handle) { handle.lastRecycledId = id; Link tail = this.tail; int writeIndex; if ((writeIndex = tail.get()) == LINK_CAPACITY) { - if (!stack.reserveSpace(LINK_CAPACITY)) { + if (!reserveSpace(LINK_CAPACITY)) { // Drop it. return; } @@ -314,7 +337,7 @@ public abstract class Recycler { if (srcEnd == LINK_CAPACITY && head.next != null) { // Add capacity back as the Link is GCed. - stack.reclaimSpace(LINK_CAPACITY); + reclaimSpace(LINK_CAPACITY); this.head = head.next; } @@ -339,7 +362,7 @@ public abstract class Recycler { private DefaultHandle[] elements; private final int maxCapacity; private int size; - private final AtomicInteger availableSharedCapacity; + final AtomicInteger availableSharedCapacity; private volatile WeakOrderQueue head; private WeakOrderQueue cursor, prev; @@ -352,24 +375,6 @@ public abstract class Recycler { elements = new DefaultHandle[min(INITIAL_CAPACITY, maxCapacity)]; } - boolean reserveSpace(int space) { - assert space >= 0; - for (;;) { - int available = availableSharedCapacity.get(); - if (available < space) { - return false; - } - if (availableSharedCapacity.compareAndSet(available, available - space)) { - return true; - } - } - } - - void reclaimSpace(int space) { - assert space >= 0; - availableSharedCapacity.addAndGet(space); - } - int increaseCapacity(int expectedCapacity) { int newCapacity = elements.length; int maxCapacity = this.maxCapacity;