From da94a908ad5b045ef5ae6d2bb8b1fcade654bf00 Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Wed, 15 Feb 2017 08:12:40 +0100 Subject: [PATCH] Prefer JDK ThreadLocalRandom implementation over ours. Motivation: We have our own ThreadLocalRandom implementation to support older JDKs . That said we should prefer the JDK provided when running on JDK >= 7 Modification: Using ThreadLocalRandom implementation of the JDK when possible. Result: Make use of JDK implementations when possible. --- .../io/netty/buffer/AbstractByteBufTest.java | 6 ++-- .../io/netty/buffer/SlicedByteBufTest.java | 9 +++--- .../multipart/HttpPostRequestEncoder.java | 4 +-- .../WebSocketClientHandshakerTest.java | 4 +-- .../codec/ByteToMessageDecoderTest.java | 7 ++--- .../handler/codec/compression/ZlibTest.java | 5 ++-- .../io/netty/util/ResourceLeakDetector.java | 4 +-- .../util/internal/PlatformDependent.java | 28 +++++++++++++++++++ .../ssl/util/ThreadLocalInsecureRandom.java | 7 +++-- .../netty/handler/ssl/OpenSslEngineTest.java | 4 +-- .../io/netty/handler/ssl/SSLEngineTest.java | 14 +++++----- pom.xml | 1 + .../socket/SocketFileRegionTest.java | 6 ++-- .../java/io/netty/test/udt/util/UnitHelp.java | 4 +-- .../io/netty/channel/AbstractChannel.java | 3 +- .../channel/nio/NioSocketChannelTest.java | 4 +-- 16 files changed, 67 insertions(+), 43 deletions(-) diff --git a/buffer/src/test/java/io/netty/buffer/AbstractByteBufTest.java b/buffer/src/test/java/io/netty/buffer/AbstractByteBufTest.java index 860bb13250..debebabc7e 100644 --- a/buffer/src/test/java/io/netty/buffer/AbstractByteBufTest.java +++ b/buffer/src/test/java/io/netty/buffer/AbstractByteBufTest.java @@ -17,9 +17,8 @@ package io.netty.buffer; import io.netty.util.CharsetUtil; import io.netty.util.IllegalReferenceCountException; -import io.netty.util.internal.ThreadLocalRandom; +import io.netty.util.internal.PlatformDependent; import org.junit.After; -import org.junit.Assume; import org.junit.Before; import org.junit.Test; @@ -34,7 +33,6 @@ import java.nio.channels.GatheringByteChannel; import java.nio.channels.ScatteringByteChannel; import java.nio.channels.WritableByteChannel; import java.util.Arrays; -import java.util.Collections; import java.util.HashSet; import java.util.Random; import java.util.Set; @@ -1813,7 +1811,7 @@ public abstract class AbstractByteBufTest { assertEquals(1, buf.remaining()); byte[] data = new byte[a]; - ThreadLocalRandom.current().nextBytes(data); + PlatformDependent.threadLocalRandom().nextBytes(data); buffer.writeBytes(data); buf = buffer.internalNioBuffer(0, a); diff --git a/buffer/src/test/java/io/netty/buffer/SlicedByteBufTest.java b/buffer/src/test/java/io/netty/buffer/SlicedByteBufTest.java index 71a7765c95..042070f5d4 100644 --- a/buffer/src/test/java/io/netty/buffer/SlicedByteBufTest.java +++ b/buffer/src/test/java/io/netty/buffer/SlicedByteBufTest.java @@ -15,12 +15,12 @@ */ package io.netty.buffer; +import io.netty.util.internal.PlatformDependent; import org.junit.Assume; import org.junit.Test; import java.io.IOException; import java.nio.ByteBuffer; -import java.util.Random; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -30,14 +30,13 @@ import static org.junit.Assert.assertTrue; * Tests sliced channel buffers */ public class SlicedByteBufTest extends AbstractByteBufTest { - - private final Random random = new Random(); - @Override protected ByteBuf newBuffer(int length, int maxCapacity) { Assume.assumeTrue(maxCapacity == Integer.MAX_VALUE); ByteBuf buffer = Unpooled.wrappedBuffer( - new byte[length * 2], random.nextInt(length - 1) + 1, length); + new byte[length * 2], length > 1 ? + PlatformDependent.threadLocalRandom().nextInt(length - 1) + 1 : 0, length); + assertEquals(0, buffer.readerIndex()); assertEquals(length, buffer.writerIndex()); return buffer; } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestEncoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestEncoder.java index 3b60e739a9..9ce495c4d6 100755 --- a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestEncoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestEncoder.java @@ -29,7 +29,7 @@ import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpVersion; import io.netty.handler.codec.http.LastHttpContent; import io.netty.handler.stream.ChunkedInput; -import io.netty.util.internal.ThreadLocalRandom; +import io.netty.util.internal.PlatformDependent; import java.io.File; import java.io.IOException; @@ -276,7 +276,7 @@ public class HttpPostRequestEncoder implements ChunkedInput { */ private static String getNewMultipartDelimiter() { // construct a generated delimiter - return Long.toHexString(ThreadLocalRandom.current().nextLong()).toLowerCase(); + return Long.toHexString(PlatformDependent.threadLocalRandom().nextLong()).toLowerCase(); } /** diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshakerTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshakerTest.java index b2fc81f9db..e7e1e24367 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshakerTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshakerTest.java @@ -29,7 +29,7 @@ import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpRequestEncoder; import io.netty.handler.codec.http.HttpResponseDecoder; import io.netty.util.CharsetUtil; -import io.netty.util.internal.ThreadLocalRandom; +import io.netty.util.internal.PlatformDependent; import org.junit.Test; import java.net.URI; @@ -102,7 +102,7 @@ public abstract class WebSocketClientHandshakerTest { }; byte[] data = new byte[24]; - ThreadLocalRandom.current().nextBytes(data); + PlatformDependent.threadLocalRandom().nextBytes(data); // Create a EmbeddedChannel which we will use to encode a BinaryWebsocketFrame to bytes and so use these // to test the actual handshaker. diff --git a/codec/src/test/java/io/netty/handler/codec/ByteToMessageDecoderTest.java b/codec/src/test/java/io/netty/handler/codec/ByteToMessageDecoderTest.java index 222bfc2c2e..149d36980e 100644 --- a/codec/src/test/java/io/netty/handler/codec/ByteToMessageDecoderTest.java +++ b/codec/src/test/java/io/netty/handler/codec/ByteToMessageDecoderTest.java @@ -20,8 +20,7 @@ import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.util.ReferenceCountUtil; -import io.netty.util.internal.ThreadLocalRandom; +import io.netty.util.internal.PlatformDependent; import org.junit.Test; import java.util.List; @@ -217,7 +216,7 @@ public class ByteToMessageDecoderTest { } }); byte[] bytes = new byte[1024]; - ThreadLocalRandom.current().nextBytes(bytes); + PlatformDependent.threadLocalRandom().nextBytes(bytes); assertTrue(channel.writeInbound(Unpooled.wrappedBuffer(bytes))); assertBuffer(Unpooled.wrappedBuffer(bytes), (ByteBuf) channel.readInbound()); @@ -249,7 +248,7 @@ public class ByteToMessageDecoderTest { } }); byte[] bytes = new byte[1024]; - ThreadLocalRandom.current().nextBytes(bytes); + PlatformDependent.threadLocalRandom().nextBytes(bytes); assertTrue(channel.writeInbound(Unpooled.wrappedBuffer(bytes))); assertBuffer(Unpooled.wrappedBuffer(bytes, 0, bytes.length - 1), (ByteBuf) channel.readInbound()); diff --git a/codec/src/test/java/io/netty/handler/codec/compression/ZlibTest.java b/codec/src/test/java/io/netty/handler/codec/compression/ZlibTest.java index 3ddbbd9205..c779ea733b 100644 --- a/codec/src/test/java/io/netty/handler/codec/compression/ZlibTest.java +++ b/codec/src/test/java/io/netty/handler/codec/compression/ZlibTest.java @@ -22,12 +22,13 @@ import io.netty.channel.embedded.EmbeddedChannel; import io.netty.util.CharsetUtil; import io.netty.util.ReferenceCountUtil; import io.netty.util.internal.EmptyArrays; -import io.netty.util.internal.ThreadLocalRandom; +import io.netty.util.internal.PlatformDependent; import org.junit.Test; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.util.Random; import java.util.zip.DeflaterOutputStream; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; @@ -82,7 +83,7 @@ public abstract class ZlibTest { "").getBytes(CharsetUtil.UTF_8); static { - ThreadLocalRandom rand = ThreadLocalRandom.current(); + Random rand = PlatformDependent.threadLocalRandom(); rand.nextBytes(BYTES_SMALL); rand.nextBytes(BYTES_LARGE); } diff --git a/common/src/main/java/io/netty/util/ResourceLeakDetector.java b/common/src/main/java/io/netty/util/ResourceLeakDetector.java index 6664cbda2f..8253edbcb7 100644 --- a/common/src/main/java/io/netty/util/ResourceLeakDetector.java +++ b/common/src/main/java/io/netty/util/ResourceLeakDetector.java @@ -18,7 +18,6 @@ package io.netty.util; import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.SystemPropertyUtil; -import io.netty.util.internal.ThreadLocalRandom; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; @@ -27,7 +26,6 @@ import java.lang.ref.ReferenceQueue; import java.util.ArrayDeque; import java.util.Deque; import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.atomic.AtomicBoolean; import static io.netty.util.internal.StringUtil.EMPTY_STRING; import static io.netty.util.internal.StringUtil.NEWLINE; @@ -246,7 +244,7 @@ public class ResourceLeakDetector { } if (level.ordinal() < Level.PARANOID.ordinal()) { - if ((ThreadLocalRandom.current().nextInt(0, samplingInterval)) == 0) { + if ((PlatformDependent.threadLocalRandom().nextInt(samplingInterval)) == 0) { reportLeak(level); return new DefaultResourceLeak(obj); } else { diff --git a/common/src/main/java/io/netty/util/internal/PlatformDependent.java b/common/src/main/java/io/netty/util/internal/PlatformDependent.java index 6797691f21..41b2d2ee44 100644 --- a/common/src/main/java/io/netty/util/internal/PlatformDependent.java +++ b/common/src/main/java/io/netty/util/internal/PlatformDependent.java @@ -44,6 +44,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Queue; +import java.util.Random; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.ConcurrentMap; @@ -102,10 +103,26 @@ public final class PlatformDependent { private static final boolean USE_DIRECT_BUFFER_NO_CLEANER; private static final AtomicLong DIRECT_MEMORY_COUNTER; private static final long DIRECT_MEMORY_LIMIT; + private static final ThreadLocalRandomProvider RANDOM_PROVIDER; public static final boolean BIG_ENDIAN_NATIVE_ORDER = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN; static { + if (javaVersion() >= 7) { + RANDOM_PROVIDER = new ThreadLocalRandomProvider() { + @Override + public Random current() { + return java.util.concurrent.ThreadLocalRandom.current(); + } + }; + } else { + RANDOM_PROVIDER = new ThreadLocalRandomProvider() { + @Override + public Random current() { + return ThreadLocalRandom.current(); + } + }; + } if (logger.isDebugEnabled()) { logger.debug("-Dio.netty.noPreferDirect: {}", !DIRECT_BUFFER_PREFERRED); } @@ -627,6 +644,13 @@ public final class PlatformDependent { } } + /** + * Return a {@link Random} which is not-threadsafe and so can only be used from the same thread. + */ + public static Random threadLocalRandom() { + return RANDOM_PROVIDER.current(); + } + private static boolean isAndroid0() { boolean android; try { @@ -1086,6 +1110,10 @@ public final class PlatformDependent { } } + private interface ThreadLocalRandomProvider { + Random current(); + } + private PlatformDependent() { // only static method supported } diff --git a/handler/src/main/java/io/netty/handler/ssl/util/ThreadLocalInsecureRandom.java b/handler/src/main/java/io/netty/handler/ssl/util/ThreadLocalInsecureRandom.java index c69f886cd5..8b2695e146 100644 --- a/handler/src/main/java/io/netty/handler/ssl/util/ThreadLocalInsecureRandom.java +++ b/handler/src/main/java/io/netty/handler/ssl/util/ThreadLocalInsecureRandom.java @@ -16,13 +16,14 @@ package io.netty.handler.ssl.util; -import io.netty.util.internal.ThreadLocalRandom; +import io.netty.util.internal.PlatformDependent; import java.security.SecureRandom; import java.util.Random; /** - * Insecure {@link java.security.SecureRandom} which relies on {@link ThreadLocalRandom} for random number generation. + * Insecure {@link SecureRandom} which relies on {@link PlatformDependent#threadLocalRandom()} for random number + * generation. */ final class ThreadLocalInsecureRandom extends SecureRandom { @@ -95,6 +96,6 @@ final class ThreadLocalInsecureRandom extends SecureRandom { } private static Random random() { - return ThreadLocalRandom.current(); + return PlatformDependent.threadLocalRandom(); } } diff --git a/handler/src/test/java/io/netty/handler/ssl/OpenSslEngineTest.java b/handler/src/test/java/io/netty/handler/ssl/OpenSslEngineTest.java index 19411127cd..08a05cc7b1 100644 --- a/handler/src/test/java/io/netty/handler/ssl/OpenSslEngineTest.java +++ b/handler/src/test/java/io/netty/handler/ssl/OpenSslEngineTest.java @@ -21,7 +21,7 @@ import io.netty.handler.ssl.ApplicationProtocolConfig.SelectedListenerFailureBeh import io.netty.handler.ssl.ApplicationProtocolConfig.SelectorFailureBehavior; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; import io.netty.handler.ssl.util.SelfSignedCertificate; -import io.netty.util.internal.ThreadLocalRandom; +import io.netty.util.internal.PlatformDependent; import org.junit.Assume; import org.junit.BeforeClass; import org.junit.Test; @@ -142,7 +142,7 @@ public class OpenSslEngineTest extends SSLEngineTest { ByteBuffer src = allocateBuffer(1024 * 10); byte[] data = new byte[src.capacity()]; - ThreadLocalRandom.current().nextBytes(data); + PlatformDependent.threadLocalRandom().nextBytes(data); src.put(data).flip(); ByteBuffer dst = allocateBuffer(1); // Try to wrap multiple times so we are more likely to hit the issue. diff --git a/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java b/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java index 21fcd6fe93..8380f1f2ce 100644 --- a/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java +++ b/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java @@ -41,7 +41,7 @@ import io.netty.util.ReferenceCountUtil; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.Promise; import io.netty.util.internal.EmptyArrays; -import io.netty.util.internal.ThreadLocalRandom; +import io.netty.util.internal.PlatformDependent; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -223,7 +223,7 @@ public abstract class SSLEngineTest { case Heap: return ByteBuffer.allocate(len); case Mixed: - return ThreadLocalRandom.current().nextBoolean() ? + return PlatformDependent.threadLocalRandom().nextBoolean() ? ByteBuffer.allocateDirect(len) : ByteBuffer.allocate(len); default: throw new Error(); @@ -248,7 +248,7 @@ public abstract class SSLEngineTest { case Heap: return allocator.heapBuffer(); case Mixed: - return ThreadLocalRandom.current().nextBoolean() ? + return PlatformDependent.threadLocalRandom().nextBoolean() ? allocator.directBuffer() : allocator.heapBuffer(); default: throw new Error(); @@ -263,7 +263,7 @@ public abstract class SSLEngineTest { case Heap: return allocator.heapBuffer(initialCapacity); case Mixed: - return ThreadLocalRandom.current().nextBoolean() ? + return PlatformDependent.threadLocalRandom().nextBoolean() ? allocator.directBuffer(initialCapacity) : allocator.heapBuffer(initialCapacity); default: throw new Error(); @@ -278,7 +278,7 @@ public abstract class SSLEngineTest { case Heap: return allocator.heapBuffer(initialCapacity, maxCapacity); case Mixed: - return ThreadLocalRandom.current().nextBoolean() ? + return PlatformDependent.threadLocalRandom().nextBoolean() ? allocator.directBuffer(initialCapacity, maxCapacity) : allocator.heapBuffer(initialCapacity, maxCapacity); default: @@ -339,7 +339,7 @@ public abstract class SSLEngineTest { case Heap: return allocator.compositeHeapBuffer(); case Mixed: - return ThreadLocalRandom.current().nextBoolean() ? + return PlatformDependent.threadLocalRandom().nextBoolean() ? allocator.compositeDirectBuffer() : allocator.compositeHeapBuffer(); default: @@ -355,7 +355,7 @@ public abstract class SSLEngineTest { case Heap: return allocator.compositeHeapBuffer(maxNumComponents); case Mixed: - return ThreadLocalRandom.current().nextBoolean() ? + return PlatformDependent.threadLocalRandom().nextBoolean() ? allocator.compositeDirectBuffer(maxNumComponents) : allocator.compositeHeapBuffer(maxNumComponents); default: diff --git a/pom.xml b/pom.xml index 461f2cc637..a1dc99c7f3 100644 --- a/pom.xml +++ b/pom.xml @@ -649,6 +649,7 @@ java.security.cert.CertPathValidatorException$BasicReason java.util.concurrent.ConcurrentLinkedDeque + java.util.concurrent.ThreadLocalRandom java.nio.ByteBuffer diff --git a/testsuite/src/main/java/io/netty/testsuite/transport/socket/SocketFileRegionTest.java b/testsuite/src/main/java/io/netty/testsuite/transport/socket/SocketFileRegionTest.java index 92616519f5..f383169427 100644 --- a/testsuite/src/main/java/io/netty/testsuite/transport/socket/SocketFileRegionTest.java +++ b/testsuite/src/main/java/io/netty/testsuite/transport/socket/SocketFileRegionTest.java @@ -26,7 +26,7 @@ import io.netty.channel.ChannelOption; import io.netty.channel.DefaultFileRegion; import io.netty.channel.FileRegion; import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.util.internal.ThreadLocalRandom; +import io.netty.util.internal.PlatformDependent; import org.junit.Test; import java.io.File; @@ -45,7 +45,7 @@ public class SocketFileRegionTest extends AbstractSocketTest { static final byte[] data = new byte[1048576 * 10]; static { - ThreadLocalRandom.current().nextBytes(data); + PlatformDependent.threadLocalRandom().nextBytes(data); } @Test @@ -104,7 +104,7 @@ public class SocketFileRegionTest extends AbstractSocketTest { file.deleteOnExit(); final FileOutputStream out = new FileOutputStream(file); - final Random random = ThreadLocalRandom.current(); + final Random random = PlatformDependent.threadLocalRandom(); // Prepend random data which will not be transferred, so that we can test non-zero start offset final int startOffset = random.nextInt(8192); diff --git a/transport-udt/src/test/java/io/netty/test/udt/util/UnitHelp.java b/transport-udt/src/test/java/io/netty/test/udt/util/UnitHelp.java index 24a411b40b..38b686d2da 100644 --- a/transport-udt/src/test/java/io/netty/test/udt/util/UnitHelp.java +++ b/transport-udt/src/test/java/io/netty/test/udt/util/UnitHelp.java @@ -18,8 +18,8 @@ package io.netty.test.udt.util; import com.barchart.udt.SocketUDT; import com.barchart.udt.StatusUDT; +import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.SocketUtils; -import io.netty.util.internal.ThreadLocalRandom; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; @@ -222,7 +222,7 @@ public final class UnitHelp { public static int[] randomIntArray(final int length, final int range) { final int[] array = new int[length]; - final Random generator = ThreadLocalRandom.current(); + final Random generator = PlatformDependent.threadLocalRandom(); for (int i = 0; i < array.length; i++) { array[i] = generator.nextInt(range); } diff --git a/transport/src/main/java/io/netty/channel/AbstractChannel.java b/transport/src/main/java/io/netty/channel/AbstractChannel.java index 06d535f343..80763a5e99 100644 --- a/transport/src/main/java/io/netty/channel/AbstractChannel.java +++ b/transport/src/main/java/io/netty/channel/AbstractChannel.java @@ -19,7 +19,6 @@ import io.netty.buffer.ByteBufAllocator; import io.netty.util.DefaultAttributeMap; import io.netty.util.ReferenceCountUtil; import io.netty.util.internal.PlatformDependent; -import io.netty.util.internal.ThreadLocalRandom; import io.netty.util.internal.ThrowableUtil; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; @@ -54,7 +53,7 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha new NotYetConnectedException(), AbstractUnsafe.class, "flush0()"); private final Channel parent; - private final long hashCode = ThreadLocalRandom.current().nextLong(); + private final long hashCode = PlatformDependent.threadLocalRandom().nextLong(); private final Unsafe unsafe; private final DefaultChannelPipeline pipeline; private final ChannelFuture succeededFuture = new SucceededChannelFuture(this, null); diff --git a/transport/src/test/java/io/netty/channel/nio/NioSocketChannelTest.java b/transport/src/test/java/io/netty/channel/nio/NioSocketChannelTest.java index fc75dda475..04195e9c45 100644 --- a/transport/src/test/java/io/netty/channel/nio/NioSocketChannelTest.java +++ b/transport/src/test/java/io/netty/channel/nio/NioSocketChannelTest.java @@ -34,7 +34,7 @@ import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.util.CharsetUtil; import io.netty.util.NetUtil; -import io.netty.util.internal.ThreadLocalRandom; +import io.netty.util.internal.PlatformDependent; import org.junit.Test; import java.io.DataInput; @@ -170,7 +170,7 @@ public class NioSocketChannelTest { // Just some random bytes byte[] bytes = new byte[1024]; - ThreadLocalRandom.current().nextBytes(bytes); + PlatformDependent.threadLocalRandom().nextBytes(bytes); Channel sc = null; Channel cc = null;