diff --git a/buffer/src/main/java/io/netty/buffer/PoolArena.java b/buffer/src/main/java/io/netty/buffer/PoolArena.java index ad1998a0f1..d1ebcacf03 100644 --- a/buffer/src/main/java/io/netty/buffer/PoolArena.java +++ b/buffer/src/main/java/io/netty/buffer/PoolArena.java @@ -724,7 +724,10 @@ abstract class PoolArena implements PoolArenaMetric { } private int offsetCacheLine(ByteBuffer memory) { - return (int) (PlatformDependent.directBufferAddress(memory) & directMemoryCacheAlignmentMask); + // 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; } @Override diff --git a/buffer/src/main/java/io/netty/buffer/PooledByteBufAllocator.java b/buffer/src/main/java/io/netty/buffer/PooledByteBufAllocator.java index e9b6c5bd13..6d9990817e 100644 --- a/buffer/src/main/java/io/netty/buffer/PooledByteBufAllocator.java +++ b/buffer/src/main/java/io/netty/buffer/PooledByteBufAllocator.java @@ -212,6 +212,9 @@ public class PooledByteBufAllocator extends AbstractByteBufAllocator { throw new IllegalArgumentException("directMemoryCacheAlignment: " + directMemoryCacheAlignment + " (expected: >= 0)"); } + if (directMemoryCacheAlignment > 0 && !isDirectMemoryCacheAlignmentSupported()) { + throw new IllegalArgumentException("directMemoryCacheAlignment is not supported"); + } if ((directMemoryCacheAlignment & -directMemoryCacheAlignment) != directMemoryCacheAlignment) { throw new IllegalArgumentException("directMemoryCacheAlignment: " @@ -379,6 +382,13 @@ public class PooledByteBufAllocator extends AbstractByteBufAllocator { return DEFAULT_NORMAL_CACHE_SIZE; } + /** + * Return {@code true} if direct memory cache aligment is supported, {@code false} otherwise. + */ + public static boolean isDirectMemoryCacheAlignmentSupported() { + return PlatformDependent.hasUnsafe(); + } + @Override public boolean isDirectBufferPooled() { return directArenas != null; diff --git a/buffer/src/test/java/io/netty/buffer/PooledByteBufAllocatorTest.java b/buffer/src/test/java/io/netty/buffer/PooledByteBufAllocatorTest.java index 935f4aaaba..043f81a485 100644 --- a/buffer/src/test/java/io/netty/buffer/PooledByteBufAllocatorTest.java +++ b/buffer/src/test/java/io/netty/buffer/PooledByteBufAllocatorTest.java @@ -19,6 +19,7 @@ package io.netty.buffer; import io.netty.util.concurrent.FastThreadLocal; import io.netty.util.concurrent.FastThreadLocalThread; import io.netty.util.internal.SystemPropertyUtil; +import org.junit.Assume; import org.junit.Test; import java.util.ArrayList; @@ -59,6 +60,7 @@ public class PooledByteBufAllocatorTest extends AbstractByteBufAllocatorTest { @Test public void testArenaMetricsCacheAlign() { + Assume.assumeTrue(PooledByteBufAllocator.isDirectMemoryCacheAlignmentSupported()); testArenaMetrics0(new PooledByteBufAllocator(true, 2, 2, 8192, 11, 1000, 1000, 1000, true, 64), 100, 1, 1, 0); }