* Fixes #10211 - NPE in ArrayByteBufferPool.findOldestEntry() Fixed algorithm to check for oldest entry to avoid NPE. Added comments for clarity. Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
This commit is contained in:
parent
86312f1d11
commit
30ed83f3d0
|
@ -382,6 +382,8 @@ public class ArrayRetainableByteBufferPool implements RetainableByteBufferPool,
|
||||||
|
|
||||||
while (totalClearedCapacity < excess)
|
while (totalClearedCapacity < excess)
|
||||||
{
|
{
|
||||||
|
// Run through all the buckets to avoid removing
|
||||||
|
// the buffers only from the first bucket(s).
|
||||||
for (RetainedBucket bucket : buckets)
|
for (RetainedBucket bucket : buckets)
|
||||||
{
|
{
|
||||||
RetainedBucket.Entry oldestEntry = findOldestEntry(now, bucket);
|
RetainedBucket.Entry oldestEntry = findOldestEntry(now, bucket);
|
||||||
|
@ -390,13 +392,14 @@ public class ArrayRetainableByteBufferPool implements RetainableByteBufferPool,
|
||||||
|
|
||||||
if (oldestEntry.remove())
|
if (oldestEntry.remove())
|
||||||
{
|
{
|
||||||
int clearedCapacity = oldestEntry.getPooled().capacity();
|
RetainableByteBuffer buffer = oldestEntry.getPooled();
|
||||||
|
int clearedCapacity = buffer.capacity();
|
||||||
if (direct)
|
if (direct)
|
||||||
_currentDirectMemory.addAndGet(-clearedCapacity);
|
_currentDirectMemory.addAndGet(-clearedCapacity);
|
||||||
else
|
else
|
||||||
_currentHeapMemory.addAndGet(-clearedCapacity);
|
_currentHeapMemory.addAndGet(-clearedCapacity);
|
||||||
totalClearedCapacity += clearedCapacity;
|
totalClearedCapacity += clearedCapacity;
|
||||||
removed(oldestEntry.getPooled());
|
removed(buffer);
|
||||||
}
|
}
|
||||||
// else a concurrent thread evicted the same entry -> do not account for its capacity.
|
// else a concurrent thread evicted the same entry -> do not account for its capacity.
|
||||||
}
|
}
|
||||||
|
@ -430,18 +433,25 @@ public class ArrayRetainableByteBufferPool implements RetainableByteBufferPool,
|
||||||
|
|
||||||
private Pool<RetainableByteBuffer>.Entry findOldestEntry(long now, Pool<RetainableByteBuffer> bucket)
|
private Pool<RetainableByteBuffer>.Entry findOldestEntry(long now, Pool<RetainableByteBuffer> bucket)
|
||||||
{
|
{
|
||||||
|
// This method may be in the hot path, do not use Java streams.
|
||||||
|
|
||||||
RetainedBucket.Entry oldestEntry = null;
|
RetainedBucket.Entry oldestEntry = null;
|
||||||
|
RetainableByteBuffer oldestBuffer = null;
|
||||||
|
long oldestAge = 0;
|
||||||
for (RetainedBucket.Entry entry : bucket.values())
|
for (RetainedBucket.Entry entry : bucket.values())
|
||||||
{
|
{
|
||||||
if (oldestEntry != null)
|
RetainableByteBuffer buffer = entry.getPooled();
|
||||||
|
// A null buffer means the entry is reserved
|
||||||
|
// but not acquired yet, try the next.
|
||||||
|
if (buffer != null)
|
||||||
{
|
{
|
||||||
long entryAge = NanoTime.elapsed(entry.getPooled().getLastUpdate(), now);
|
long age = NanoTime.elapsed(buffer.getLastUpdate(), now);
|
||||||
if (entryAge > NanoTime.elapsed(oldestEntry.getPooled().getLastUpdate(), now))
|
if (oldestBuffer == null || age > oldestAge)
|
||||||
|
{
|
||||||
oldestEntry = entry;
|
oldestEntry = entry;
|
||||||
}
|
oldestBuffer = buffer;
|
||||||
else
|
oldestAge = age;
|
||||||
{
|
}
|
||||||
oldestEntry = entry;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return oldestEntry;
|
return oldestEntry;
|
||||||
|
|
Loading…
Reference in New Issue