From b5989e244917250bae6b925e817ee752ef7aede6 Mon Sep 17 00:00:00 2001 From: Trustin Lee Date: Wed, 24 Apr 2013 09:32:53 +0900 Subject: [PATCH] Reduce exception instantiation overhead in SslHandler / Reduce unnecessary empty array creation - Added EmptyArrays as an internal utility class --- .../netty/buffer/DefaultCompositeByteBuf.java | 5 +-- .../java/io/netty/buffer/EmptyByteBuf.java | 4 +- .../io/netty/buffer/AbstractByteBufTest.java | 6 +-- .../buffer/AbstractCompositeByteBufTest.java | 4 +- .../io/netty/buffer/ByteBufStreamTest.java | 4 +- .../java/io/netty/buffer/UnpooledTest.java | 45 ++++++++++--------- .../http/multipart/AbstractDiskHttpData.java | 3 +- .../http/websocketx/CloseWebSocketFrame.java | 5 +-- .../websocketx/WebSocketServerHandshaker.java | 5 +-- .../codec/spdy/SpdySessionHandler.java | 7 ++- .../codec/compression/JZlibEncoder.java | 5 +-- .../codec/bytes/ByteArrayDecoderTest.java | 3 +- .../codec/bytes/ByteArrayEncoderTest.java | 4 +- .../io/netty/util/internal/EmptyArrays.java | 36 +++++++++++++++ .../java/io/netty/handler/ssl/SslHandler.java | 29 +++++++----- .../ThreadPerChannelEventLoopGroup.java | 8 ++-- .../socket/oio/OioDatagramChannel.java | 5 +-- 17 files changed, 110 insertions(+), 68 deletions(-) create mode 100644 common/src/main/java/io/netty/util/internal/EmptyArrays.java diff --git a/buffer/src/main/java/io/netty/buffer/DefaultCompositeByteBuf.java b/buffer/src/main/java/io/netty/buffer/DefaultCompositeByteBuf.java index 1fee2a1132..95ff71e535 100644 --- a/buffer/src/main/java/io/netty/buffer/DefaultCompositeByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/DefaultCompositeByteBuf.java @@ -16,6 +16,7 @@ package io.netty.buffer; import io.netty.util.ResourceLeak; +import io.netty.util.internal.EmptyArrays; import io.netty.util.internal.PlatformDependent; import java.io.IOException; @@ -42,8 +43,6 @@ import java.util.Queue; */ public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf implements CompositeByteBuf { - private static final ByteBuffer[] EMPTY_NIOBUFFERS = new ByteBuffer[0]; - private final ResourceLeak leak; private final ByteBufAllocator alloc; private final boolean direct; @@ -1049,7 +1048,7 @@ public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf imp public ByteBuffer[] nioBuffers(int index, int length) { checkIndex(index, length); if (length == 0) { - return EMPTY_NIOBUFFERS; + return EmptyArrays.EMPTY_BYTE_BUFFERS; } List buffers = new ArrayList(components.size()); diff --git a/buffer/src/main/java/io/netty/buffer/EmptyByteBuf.java b/buffer/src/main/java/io/netty/buffer/EmptyByteBuf.java index b76eeb2d09..07745ec127 100644 --- a/buffer/src/main/java/io/netty/buffer/EmptyByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/EmptyByteBuf.java @@ -16,6 +16,7 @@ package io.netty.buffer; +import io.netty.util.internal.EmptyArrays; import io.netty.util.internal.PlatformDependent; import java.io.InputStream; @@ -32,7 +33,6 @@ import java.nio.charset.Charset; */ public final class EmptyByteBuf implements ByteBuf { - private static final byte[] EMPTY_ARRAY = new byte[0]; private static final ByteBuffer EMPTY_BYTE_BUFFER = ByteBuffer.allocateDirect(0); private static final long EMPTY_BYTE_BUFFER_ADDRESS; @@ -767,7 +767,7 @@ public final class EmptyByteBuf implements ByteBuf { @Override public byte[] array() { - return EMPTY_ARRAY; + return EmptyArrays.EMPTY_BYTES; } @Override diff --git a/buffer/src/test/java/io/netty/buffer/AbstractByteBufTest.java b/buffer/src/test/java/io/netty/buffer/AbstractByteBufTest.java index e2fe39166b..fdcbd02cde 100644 --- a/buffer/src/test/java/io/netty/buffer/AbstractByteBufTest.java +++ b/buffer/src/test/java/io/netty/buffer/AbstractByteBufTest.java @@ -32,6 +32,7 @@ import java.util.Random; import java.util.Set; import static io.netty.buffer.Unpooled.*; +import static io.netty.util.internal.EmptyArrays.*; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; @@ -42,7 +43,6 @@ public abstract class AbstractByteBufTest { private static final int CAPACITY = 4096; // Must be even private static final int BLOCK_SIZE = 128; - private static final byte[] EMPTY_ARRAY = new byte[0]; private static final Queue freeLaterQueue = new ArrayDeque(); @@ -235,12 +235,12 @@ public abstract class AbstractByteBufTest { @Test(expected = IndexOutOfBoundsException.class) public void getByteArrayBoundaryCheck1() { - buffer.getBytes(-1, EMPTY_ARRAY); + buffer.getBytes(-1, EMPTY_BYTES); } @Test(expected = IndexOutOfBoundsException.class) public void getByteArrayBoundaryCheck2() { - buffer.getBytes(-1, EMPTY_ARRAY, 0, 0); + buffer.getBytes(-1, EMPTY_BYTES, 0, 0); } @Test diff --git a/buffer/src/test/java/io/netty/buffer/AbstractCompositeByteBufTest.java b/buffer/src/test/java/io/netty/buffer/AbstractCompositeByteBufTest.java index 9e08b23b39..584f96a6b0 100644 --- a/buffer/src/test/java/io/netty/buffer/AbstractCompositeByteBufTest.java +++ b/buffer/src/test/java/io/netty/buffer/AbstractCompositeByteBufTest.java @@ -24,13 +24,13 @@ import java.util.Collections; import java.util.List; import static io.netty.buffer.Unpooled.*; +import static io.netty.util.internal.EmptyArrays.*; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; /** * An abstract test class for composite channel buffers */ -@SuppressWarnings("ZeroLengthArrayAllocation") public abstract class AbstractCompositeByteBufTest extends AbstractByteBufTest { private final ByteOrder order; @@ -418,7 +418,7 @@ public abstract class AbstractCompositeByteBufTest extends AbstractByteBufTest { public void testEmptyBuffer() { ByteBuf b = freeLater(wrappedBuffer(new byte[]{1, 2}, new byte[]{3, 4})); b.readBytes(new byte[4]); - b.readBytes(new byte[0]); + b.readBytes(EMPTY_BYTES); } // Test for https://github.com/netty/netty/issues/1060 diff --git a/buffer/src/test/java/io/netty/buffer/ByteBufStreamTest.java b/buffer/src/test/java/io/netty/buffer/ByteBufStreamTest.java index e23169219e..430df8ff5d 100644 --- a/buffer/src/test/java/io/netty/buffer/ByteBufStreamTest.java +++ b/buffer/src/test/java/io/netty/buffer/ByteBufStreamTest.java @@ -20,12 +20,12 @@ import org.junit.Test; import java.io.EOFException; import java.nio.charset.Charset; +import static io.netty.util.internal.EmptyArrays.*; import static org.junit.Assert.*; /** * Tests channel buffer streams */ -@SuppressWarnings("ZeroLengthArrayAllocation") public class ByteBufStreamTest { @Test @@ -56,7 +56,7 @@ public class ByteBufStreamTest { out.writeShort(49152); out.writeUTF("Hello, World!"); out.writeBytes("The first line\r\r\n"); - out.write(new byte[0]); + out.write(EMPTY_BYTES); out.write(new byte[] { 1, 2, 3, 4 }); out.write(new byte[] { 1, 3, 3, 4 }, 0, 0); out.close(); diff --git a/buffer/src/test/java/io/netty/buffer/UnpooledTest.java b/buffer/src/test/java/io/netty/buffer/UnpooledTest.java index 5258b4f592..07859fa680 100644 --- a/buffer/src/test/java/io/netty/buffer/UnpooledTest.java +++ b/buffer/src/test/java/io/netty/buffer/UnpooledTest.java @@ -31,14 +31,17 @@ import java.util.Map.Entry; import java.util.Queue; import static io.netty.buffer.Unpooled.*; +import static io.netty.util.internal.EmptyArrays.*; import static org.junit.Assert.*; /** * Tests channel buffers */ -@SuppressWarnings("ZeroLengthArrayAllocation") public class UnpooledTest { + private static final ByteBuf[] EMPTY_BYTE_BUFS = new ByteBuf[0]; + private static final byte[][] EMPTY_BYTES_2D = new byte[0][]; + private static final Queue freeLaterQueue = new ArrayDeque(); protected ByteBuf freeLater(ByteBuf buf) { @@ -82,7 +85,7 @@ public class UnpooledTest { @Test public void testHashCode() { Map map = new LinkedHashMap(); - map.put(new byte[0], 1); + map.put(EMPTY_BYTES, 1); map.put(new byte[] { 1 }, 32); map.put(new byte[] { 2 }, 33); map.put(new byte[] { 0, 1 }, 962); @@ -183,31 +186,31 @@ public class UnpooledTest { @Test public void shouldReturnEmptyBufferWhenLengthIsZero() { - assertSame(EMPTY_BUFFER, wrappedBuffer(new byte[0])); + assertSame(EMPTY_BUFFER, wrappedBuffer(EMPTY_BYTES)); assertSame(EMPTY_BUFFER, wrappedBuffer(new byte[8], 0, 0)); assertSame(EMPTY_BUFFER, wrappedBuffer(new byte[8], 8, 0)); assertSame(EMPTY_BUFFER, wrappedBuffer(ByteBuffer.allocateDirect(0))); assertSame(EMPTY_BUFFER, wrappedBuffer(EMPTY_BUFFER)); - assertSame(EMPTY_BUFFER, wrappedBuffer(new byte[0][])); - assertSame(EMPTY_BUFFER, wrappedBuffer(new byte[][] { new byte[0] })); - assertSame(EMPTY_BUFFER, wrappedBuffer(new ByteBuffer[0])); + assertSame(EMPTY_BUFFER, wrappedBuffer(EMPTY_BYTES_2D)); + assertSame(EMPTY_BUFFER, wrappedBuffer(new byte[][] { EMPTY_BYTES })); + assertSame(EMPTY_BUFFER, wrappedBuffer(EMPTY_BYTE_BUFFERS)); assertSame(EMPTY_BUFFER, wrappedBuffer(new ByteBuffer[] { ByteBuffer.allocate(0) })); assertSame(EMPTY_BUFFER, wrappedBuffer(ByteBuffer.allocate(0), ByteBuffer.allocate(0))); - assertSame(EMPTY_BUFFER, wrappedBuffer(new ByteBuf[0])); + assertSame(EMPTY_BUFFER, wrappedBuffer(EMPTY_BYTE_BUFS)); assertSame(EMPTY_BUFFER, wrappedBuffer(new ByteBuf[] { buffer(0) })); assertSame(EMPTY_BUFFER, wrappedBuffer(buffer(0), buffer(0))); - assertSame(EMPTY_BUFFER, copiedBuffer(new byte[0])); + assertSame(EMPTY_BUFFER, copiedBuffer(EMPTY_BYTES)); assertSame(EMPTY_BUFFER, copiedBuffer(new byte[8], 0, 0)); assertSame(EMPTY_BUFFER, copiedBuffer(new byte[8], 8, 0)); assertSame(EMPTY_BUFFER, copiedBuffer(ByteBuffer.allocateDirect(0))); assertSame(EMPTY_BUFFER, copiedBuffer(EMPTY_BUFFER)); - assertSame(EMPTY_BUFFER, copiedBuffer(new byte[0][])); - assertSame(EMPTY_BUFFER, copiedBuffer(new byte[][] { new byte[0] })); - assertSame(EMPTY_BUFFER, copiedBuffer(new ByteBuffer[0])); + assertSame(EMPTY_BUFFER, copiedBuffer(EMPTY_BYTES_2D)); + assertSame(EMPTY_BUFFER, copiedBuffer(new byte[][] { EMPTY_BYTES })); + assertSame(EMPTY_BUFFER, copiedBuffer(EMPTY_BYTE_BUFFERS)); assertSame(EMPTY_BUFFER, copiedBuffer(new ByteBuffer[] { ByteBuffer.allocate(0) })); assertSame(EMPTY_BUFFER, copiedBuffer(ByteBuffer.allocate(0), ByteBuffer.allocate(0))); - assertSame(EMPTY_BUFFER, copiedBuffer(new ByteBuf[0])); + assertSame(EMPTY_BUFFER, copiedBuffer(EMPTY_BYTE_BUFS)); assertSame(EMPTY_BUFFER, copiedBuffer(new ByteBuf[] { buffer(0) })); assertSame(EMPTY_BUFFER, copiedBuffer(buffer(0), buffer(0))); } @@ -370,7 +373,7 @@ public class UnpooledTest { } try { - buf.setBytes(0, new byte[0], 0, 0); + buf.setBytes(0, EMPTY_BYTES, 0, 0); fail(); } catch (UnsupportedOperationException e) { // Expected @@ -443,7 +446,7 @@ public class UnpooledTest { assertFalse(buffer.isReadable()); assertEquals(0, Unpooled.copyInt(null).capacity()); - assertEquals(0, Unpooled.copyInt(new int[0]).capacity()); + assertEquals(0, Unpooled.copyInt(EMPTY_INTS).capacity()); } @Test @@ -463,7 +466,7 @@ public class UnpooledTest { assertFalse(buffer.isReadable()); assertEquals(0, Unpooled.copyShort((short[]) null).capacity()); - assertEquals(0, Unpooled.copyShort(new short[0]).capacity()); + assertEquals(0, Unpooled.copyShort(EMPTY_SHORTS).capacity()); } @Test @@ -475,7 +478,7 @@ public class UnpooledTest { assertFalse(buffer.isReadable()); assertEquals(0, Unpooled.copyShort((int[]) null).capacity()); - assertEquals(0, Unpooled.copyShort(new int[0]).capacity()); + assertEquals(0, Unpooled.copyShort(EMPTY_INTS).capacity()); } @Test @@ -495,7 +498,7 @@ public class UnpooledTest { assertFalse(buffer.isReadable()); assertEquals(0, Unpooled.copyMedium(null).capacity()); - assertEquals(0, Unpooled.copyMedium(new int[0]).capacity()); + assertEquals(0, Unpooled.copyMedium(EMPTY_INTS).capacity()); } @Test @@ -515,7 +518,7 @@ public class UnpooledTest { assertFalse(buffer.isReadable()); assertEquals(0, Unpooled.copyLong(null).capacity()); - assertEquals(0, Unpooled.copyLong(new long[0]).capacity()); + assertEquals(0, Unpooled.copyLong(EMPTY_LONGS).capacity()); } @Test @@ -535,7 +538,7 @@ public class UnpooledTest { assertFalse(buffer.isReadable()); assertEquals(0, Unpooled.copyFloat(null).capacity()); - assertEquals(0, Unpooled.copyFloat(new float[0]).capacity()); + assertEquals(0, Unpooled.copyFloat(EMPTY_FLOATS).capacity()); } @Test @@ -555,7 +558,7 @@ public class UnpooledTest { assertFalse(buffer.isReadable()); assertEquals(0, Unpooled.copyDouble(null).capacity()); - assertEquals(0, Unpooled.copyDouble(new double[0]).capacity()); + assertEquals(0, Unpooled.copyDouble(EMPTY_DOUBLES).capacity()); } @Test @@ -567,7 +570,7 @@ public class UnpooledTest { assertFalse(buffer.isReadable()); assertEquals(0, Unpooled.copyBoolean(null).capacity()); - assertEquals(0, Unpooled.copyBoolean(new boolean[0]).capacity()); + assertEquals(0, Unpooled.copyBoolean(EMPTY_BOOLEANS).capacity()); } @Test diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/AbstractDiskHttpData.java b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/AbstractDiskHttpData.java index c854a719d2..eec1bd76a7 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/AbstractDiskHttpData.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/AbstractDiskHttpData.java @@ -17,6 +17,7 @@ package io.netty.handler.codec.http.multipart; import io.netty.buffer.ByteBuf; import io.netty.handler.codec.http.HttpConstants; +import io.netty.util.internal.EmptyArrays; import java.io.File; import java.io.FileInputStream; @@ -222,7 +223,7 @@ public abstract class AbstractDiskHttpData extends AbstractHttpData { @Override public byte[] get() throws IOException { if (file == null) { - return new byte[0]; + return EmptyArrays.EMPTY_BYTES; } return readFrom(file); } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/CloseWebSocketFrame.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/CloseWebSocketFrame.java index 3df1707d3b..cb5f2d3460 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/CloseWebSocketFrame.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/CloseWebSocketFrame.java @@ -18,14 +18,13 @@ package io.netty.handler.codec.http.websocketx; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.util.CharsetUtil; +import io.netty.util.internal.EmptyArrays; /** * Web Socket Frame for closing the connection */ public class CloseWebSocketFrame extends WebSocketFrame { - private static final byte[] EMTPY_REASON = new byte[0]; - /** * Creates a new empty close frame. */ @@ -76,7 +75,7 @@ public class CloseWebSocketFrame extends WebSocketFrame { } private static ByteBuf newBinaryData(int statusCode, String reasonText) { - byte[] reasonBytes = EMTPY_REASON; + byte[] reasonBytes = EmptyArrays.EMPTY_BYTES; if (reasonText != null) { reasonBytes = reasonText.getBytes(CharsetUtil.UTF_8); } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker.java index dc6bfbe497..e8b78996d6 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker.java @@ -30,6 +30,7 @@ import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpRequestDecoder; import io.netty.handler.codec.http.HttpResponseEncoder; import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.util.internal.EmptyArrays; import io.netty.util.internal.StringUtil; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; @@ -44,8 +45,6 @@ import java.util.Set; public abstract class WebSocketServerHandshaker { protected static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocketServerHandshaker.class); - private static final String[] EMPTY_ARRAY = new String[0]; - private final String uri; private final String[] subprotocols; @@ -81,7 +80,7 @@ public abstract class WebSocketServerHandshaker { } this.subprotocols = subprotocolArray; } else { - this.subprotocols = EMPTY_ARRAY; + this.subprotocols = EmptyArrays.EMPTY_STRINGS; } this.maxFramePayloadLength = maxFramePayloadLength; } diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdySessionHandler.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdySessionHandler.java index 30de843ff8..0e283af67f 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdySessionHandler.java +++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdySessionHandler.java @@ -24,6 +24,7 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundMessageHandler; import io.netty.channel.ChannelOutboundMessageHandler; import io.netty.channel.ChannelPromise; +import io.netty.util.internal.EmptyArrays; import java.util.concurrent.atomic.AtomicInteger; @@ -38,10 +39,8 @@ public class SpdySessionHandler private static final SpdyProtocolException STREAM_CLOSED = new SpdyProtocolException("Stream closed"); static { - @SuppressWarnings("ZeroLengthArrayAllocation") - StackTraceElement[] emptyTrace = new StackTraceElement[0]; - PROTOCOL_EXCEPTION.setStackTrace(emptyTrace); - STREAM_CLOSED.setStackTrace(emptyTrace); + PROTOCOL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); + STREAM_CLOSED.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); } private final SpdySession spdySession = new SpdySession(); diff --git a/codec/src/main/java/io/netty/handler/codec/compression/JZlibEncoder.java b/codec/src/main/java/io/netty/handler/codec/compression/JZlibEncoder.java index 584479ed73..9a4d57a8a0 100644 --- a/codec/src/main/java/io/netty/handler/codec/compression/JZlibEncoder.java +++ b/codec/src/main/java/io/netty/handler/codec/compression/JZlibEncoder.java @@ -23,6 +23,7 @@ import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; +import io.netty.util.internal.EmptyArrays; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; @@ -33,8 +34,6 @@ import java.util.concurrent.atomic.AtomicBoolean; */ public class JZlibEncoder extends ZlibEncoder { - private static final byte[] EMPTY_ARRAY = new byte[0]; - private final Deflater z = new Deflater(); private final AtomicBoolean finished = new AtomicBoolean(); private volatile ChannelHandlerContext ctx; @@ -367,7 +366,7 @@ public class JZlibEncoder extends ZlibEncoder { synchronized (z) { try { // Configure input. - z.next_in = EMPTY_ARRAY; + z.next_in = EmptyArrays.EMPTY_BYTES; z.next_in_index = 0; z.avail_in = 0; diff --git a/codec/src/test/java/io/netty/handler/codec/bytes/ByteArrayDecoderTest.java b/codec/src/test/java/io/netty/handler/codec/bytes/ByteArrayDecoderTest.java index f958bd4087..0f390249ca 100644 --- a/codec/src/test/java/io/netty/handler/codec/bytes/ByteArrayDecoderTest.java +++ b/codec/src/test/java/io/netty/handler/codec/bytes/ByteArrayDecoderTest.java @@ -16,6 +16,7 @@ package io.netty.handler.codec.bytes; import io.netty.channel.embedded.EmbeddedMessageChannel; +import io.netty.util.internal.EmptyArrays; import org.junit.Before; import org.junit.Test; @@ -48,7 +49,7 @@ public class ByteArrayDecoderTest { @Test public void testDecodeEmpty() { ch.writeInbound(EMPTY_BUFFER); - assertThat((byte[]) ch.readInbound(), is(new byte[0])); + assertThat((byte[]) ch.readInbound(), is(EmptyArrays.EMPTY_BYTES)); } @Test diff --git a/codec/src/test/java/io/netty/handler/codec/bytes/ByteArrayEncoderTest.java b/codec/src/test/java/io/netty/handler/codec/bytes/ByteArrayEncoderTest.java index 313f36686f..c190ee3949 100644 --- a/codec/src/test/java/io/netty/handler/codec/bytes/ByteArrayEncoderTest.java +++ b/codec/src/test/java/io/netty/handler/codec/bytes/ByteArrayEncoderTest.java @@ -17,6 +17,7 @@ package io.netty.handler.codec.bytes; import io.netty.buffer.ByteBuf; import io.netty.channel.embedded.EmbeddedMessageChannel; +import io.netty.util.internal.EmptyArrays; import org.junit.Before; import org.junit.Test; @@ -47,8 +48,7 @@ public class ByteArrayEncoderTest { @Test public void testEncodeEmpty() { - byte[] b = new byte[0]; - ch.writeOutbound(b); + ch.writeOutbound(EmptyArrays.EMPTY_BYTES); assertThat(ch.readOutbound(), nullValue()); } diff --git a/common/src/main/java/io/netty/util/internal/EmptyArrays.java b/common/src/main/java/io/netty/util/internal/EmptyArrays.java new file mode 100644 index 0000000000..d4e46685a6 --- /dev/null +++ b/common/src/main/java/io/netty/util/internal/EmptyArrays.java @@ -0,0 +1,36 @@ +/* + * Copyright 2013 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +package io.netty.util.internal; + +import java.nio.ByteBuffer; + +public final class EmptyArrays { + + public static final byte[] EMPTY_BYTES = new byte[0]; + public static final boolean[] EMPTY_BOOLEANS = new boolean[0]; + public static final double[] EMPTY_DOUBLES = new double[0]; + public static final float[] EMPTY_FLOATS = new float[0]; + public static final int[] EMPTY_INTS = new int[0]; + public static final short[] EMPTY_SHORTS = new short[0]; + public static final long[] EMPTY_LONGS = new long[0]; + public static final Object[] EMPTY_OBJECTS = new Object[0]; + public static final String[] EMPTY_STRINGS = new String[0]; + public static final StackTraceElement[] EMPTY_STACK_TRACE = new StackTraceElement[0]; + public static final ByteBuffer[] EMPTY_BYTE_BUFFERS = new ByteBuffer[0]; + + private EmptyArrays() { } +} diff --git a/handler/src/main/java/io/netty/handler/ssl/SslHandler.java b/handler/src/main/java/io/netty/handler/ssl/SslHandler.java index 5bbab16760..257ef3b013 100644 --- a/handler/src/main/java/io/netty/handler/ssl/SslHandler.java +++ b/handler/src/main/java/io/netty/handler/ssl/SslHandler.java @@ -35,6 +35,7 @@ import io.netty.util.concurrent.EventExecutor; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.GenericFutureListener; import io.netty.util.concurrent.ImmediateExecutor; +import io.netty.util.internal.EmptyArrays; import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; @@ -163,6 +164,16 @@ public class SslHandler "^.*(?:connection.*reset|connection.*closed|broken.*pipe).*$", Pattern.CASE_INSENSITIVE); + private static final SSLException SSLENGINE_CLOSED = new SSLException("SSLEngine closed already"); + private static final SSLException HANDSHAKE_TIMED_OUT = new SSLException("handshake timed out"); + private static final ClosedChannelException CHANNEL_CLOSED = new ClosedChannelException(); + + static { + SSLENGINE_CLOSED.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); + HANDSHAKE_TIMED_OUT.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); + CHANNEL_CLOSED.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); + } + private volatile ChannelHandlerContext ctx; private final SSLEngine engine; private final Executor delegatedTaskExecutor; @@ -479,10 +490,9 @@ public class SslHandler // Any further write attempts should be denied. if (in.isReadable()) { in.clear(); - SSLException e = new SSLException("SSLEngine already closed"); - promise.setFailure(e); - ctx.fireExceptionCaught(e); - flush0(ctx, bytesConsumed, e); + promise.setFailure(SSLENGINE_CLOSED); + ctx.fireExceptionCaught(SSLENGINE_CLOSED); + flush0(ctx, bytesConsumed, SSLENGINE_CLOSED); bytesConsumed = 0; } break; @@ -597,9 +607,9 @@ public class SslHandler @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { - // Make sure the handshake future is notified when a connection has - // been closed during handshake. - setHandshakeFailure(new ClosedChannelException()); + // Make sure to release SSLEngine, + // and notify the handshake future if the connection has been closed during handshake. + setHandshakeFailure(CHANNEL_CLOSED); try { inboundBufferUpdated(ctx); @@ -983,9 +993,8 @@ public class SslHandler return; } - SSLException e = new SSLException("handshake timed out"); - if (handshakePromise.tryFailure(e)) { - ctx.fireExceptionCaught(e); + if (handshakePromise.tryFailure(HANDSHAKE_TIMED_OUT)) { + ctx.fireExceptionCaught(HANDSHAKE_TIMED_OUT); ctx.close(); } } diff --git a/transport/src/main/java/io/netty/channel/ThreadPerChannelEventLoopGroup.java b/transport/src/main/java/io/netty/channel/ThreadPerChannelEventLoopGroup.java index 8ffa789ba5..f28a040d17 100644 --- a/transport/src/main/java/io/netty/channel/ThreadPerChannelEventLoopGroup.java +++ b/transport/src/main/java/io/netty/channel/ThreadPerChannelEventLoopGroup.java @@ -18,6 +18,7 @@ package io.netty.channel; import io.netty.util.concurrent.AbstractEventExecutorGroup; import io.netty.util.concurrent.EventExecutor; +import io.netty.util.internal.EmptyArrays; import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.ReadOnlyIterator; @@ -35,9 +36,6 @@ import java.util.concurrent.TimeUnit; */ public class ThreadPerChannelEventLoopGroup extends AbstractEventExecutorGroup implements EventLoopGroup { - private static final Object[] NO_ARGS = new Object[0]; - private static final StackTraceElement[] STACK_ELEMENTS = new StackTraceElement[0]; - private final Object[] childArgs; private final int maxChannels; final ThreadFactory threadFactory; @@ -88,7 +86,7 @@ public class ThreadPerChannelEventLoopGroup extends AbstractEventExecutorGroup i } if (args == null) { - childArgs = NO_ARGS; + childArgs = EmptyArrays.EMPTY_OBJECTS; } else { childArgs = args.clone(); } @@ -97,7 +95,7 @@ public class ThreadPerChannelEventLoopGroup extends AbstractEventExecutorGroup i this.threadFactory = threadFactory; tooManyChannels = new ChannelException("too many channels (max: " + maxChannels + ')'); - tooManyChannels.setStackTrace(STACK_ELEMENTS); + tooManyChannels.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); } /** diff --git a/transport/src/main/java/io/netty/channel/socket/oio/OioDatagramChannel.java b/transport/src/main/java/io/netty/channel/socket/oio/OioDatagramChannel.java index f9fbe57d5f..29e59e7429 100755 --- a/transport/src/main/java/io/netty/channel/socket/oio/OioDatagramChannel.java +++ b/transport/src/main/java/io/netty/channel/socket/oio/OioDatagramChannel.java @@ -27,6 +27,7 @@ import io.netty.channel.socket.DatagramChannel; import io.netty.channel.socket.DatagramChannelConfig; import io.netty.channel.socket.DatagramPacket; import io.netty.channel.socket.DefaultDatagramChannelConfig; +import io.netty.util.internal.EmptyArrays; import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; @@ -52,11 +53,9 @@ public class OioDatagramChannel extends AbstractOioMessageChannel private static final ChannelMetadata METADATA = new ChannelMetadata(BufType.MESSAGE, true); - private static final byte[] EMPTY_DATA = new byte[0]; - private final MulticastSocket socket; private final DatagramChannelConfig config; - private final java.net.DatagramPacket tmpPacket = new java.net.DatagramPacket(EMPTY_DATA, 0); + private final java.net.DatagramPacket tmpPacket = new java.net.DatagramPacket(EmptyArrays.EMPTY_BYTES, 0); private static MulticastSocket newSocket() { try {