diff --git a/buffer/src/main/java/io/netty/buffer/PoolArena.java b/buffer/src/main/java/io/netty/buffer/PoolArena.java index 465315b674..08d7a38e91 100644 --- a/buffer/src/main/java/io/netty/buffer/PoolArena.java +++ b/buffer/src/main/java/io/netty/buffer/PoolArena.java @@ -725,11 +725,16 @@ abstract class PoolArena implements PoolArenaMetric { return true; } - private int offsetCacheLine(ByteBuffer memory) { + // mark as package-private, only for unit test + int offsetCacheLine(ByteBuffer memory) { // We can only calculate the offset if Unsafe is present as otherwise directBufferAddress(...) will // throw an NPE. - return HAS_UNSAFE ? - (int) (PlatformDependent.directBufferAddress(memory) & directMemoryCacheAlignmentMask) : 0; + int remainder = HAS_UNSAFE + ? (int) (PlatformDependent.directBufferAddress(memory) & directMemoryCacheAlignmentMask) + : 0; + + // offset = alignment - address & (alignment - 1) + return directMemoryCacheAlignment - remainder; } @Override diff --git a/buffer/src/test/java/io/netty/buffer/PoolArenaTest.java b/buffer/src/test/java/io/netty/buffer/PoolArenaTest.java index 3fafef9c04..2c1bd12db3 100644 --- a/buffer/src/test/java/io/netty/buffer/PoolArenaTest.java +++ b/buffer/src/test/java/io/netty/buffer/PoolArenaTest.java @@ -16,6 +16,7 @@ package io.netty.buffer; +import io.netty.util.internal.PlatformDependent; import org.junit.Assert; import org.junit.Test; @@ -43,6 +44,25 @@ public class PoolArenaTest { } } + @Test + public void testDirectArenaOffsetCacheLine() throws Exception { + int capacity = 5; + int alignment = 128; + + for (int i = 0; i < 1000; i++) { + ByteBuffer bb = PlatformDependent.useDirectBufferNoCleaner() + ? PlatformDependent.allocateDirectNoCleaner(capacity + alignment) + : ByteBuffer.allocateDirect(capacity + alignment); + + PoolArena.DirectArena arena = new PoolArena.DirectArena(null, 0, 0, 9, 9, alignment); + int offset = arena.offsetCacheLine(bb); + long address = PlatformDependent.directBufferAddress(bb); + + Assert.assertEquals(0, (offset + address) & (alignment - 1)); + PlatformDependent.freeDirectBuffer(bb); + } + } + @Test public final void testAllocationCounter() { final PooledByteBufAllocator allocator = new PooledByteBufAllocator(