Reduce exception instantiation overhead in SslHandler / Reduce unnecessary empty array creation

- Added EmptyArrays as an internal utility class
This commit is contained in:
Trustin Lee 2013-04-24 09:32:53 +09:00
parent c95796d981
commit b5989e2449
17 changed files with 110 additions and 68 deletions

View File

@ -16,6 +16,7 @@
package io.netty.buffer; package io.netty.buffer;
import io.netty.util.ResourceLeak; import io.netty.util.ResourceLeak;
import io.netty.util.internal.EmptyArrays;
import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.PlatformDependent;
import java.io.IOException; import java.io.IOException;
@ -42,8 +43,6 @@ import java.util.Queue;
*/ */
public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf implements CompositeByteBuf { public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf implements CompositeByteBuf {
private static final ByteBuffer[] EMPTY_NIOBUFFERS = new ByteBuffer[0];
private final ResourceLeak leak; private final ResourceLeak leak;
private final ByteBufAllocator alloc; private final ByteBufAllocator alloc;
private final boolean direct; private final boolean direct;
@ -1049,7 +1048,7 @@ public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf imp
public ByteBuffer[] nioBuffers(int index, int length) { public ByteBuffer[] nioBuffers(int index, int length) {
checkIndex(index, length); checkIndex(index, length);
if (length == 0) { if (length == 0) {
return EMPTY_NIOBUFFERS; return EmptyArrays.EMPTY_BYTE_BUFFERS;
} }
List<ByteBuffer> buffers = new ArrayList<ByteBuffer>(components.size()); List<ByteBuffer> buffers = new ArrayList<ByteBuffer>(components.size());

View File

@ -16,6 +16,7 @@
package io.netty.buffer; package io.netty.buffer;
import io.netty.util.internal.EmptyArrays;
import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.PlatformDependent;
import java.io.InputStream; import java.io.InputStream;
@ -32,7 +33,6 @@ import java.nio.charset.Charset;
*/ */
public final class EmptyByteBuf implements ByteBuf { 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 ByteBuffer EMPTY_BYTE_BUFFER = ByteBuffer.allocateDirect(0);
private static final long EMPTY_BYTE_BUFFER_ADDRESS; private static final long EMPTY_BYTE_BUFFER_ADDRESS;
@ -767,7 +767,7 @@ public final class EmptyByteBuf implements ByteBuf {
@Override @Override
public byte[] array() { public byte[] array() {
return EMPTY_ARRAY; return EmptyArrays.EMPTY_BYTES;
} }
@Override @Override

View File

@ -32,6 +32,7 @@ import java.util.Random;
import java.util.Set; import java.util.Set;
import static io.netty.buffer.Unpooled.*; import static io.netty.buffer.Unpooled.*;
import static io.netty.util.internal.EmptyArrays.*;
import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*; 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 CAPACITY = 4096; // Must be even
private static final int BLOCK_SIZE = 128; private static final int BLOCK_SIZE = 128;
private static final byte[] EMPTY_ARRAY = new byte[0];
private static final Queue<ByteBuf> freeLaterQueue = new ArrayDeque<ByteBuf>(); private static final Queue<ByteBuf> freeLaterQueue = new ArrayDeque<ByteBuf>();
@ -235,12 +235,12 @@ public abstract class AbstractByteBufTest {
@Test(expected = IndexOutOfBoundsException.class) @Test(expected = IndexOutOfBoundsException.class)
public void getByteArrayBoundaryCheck1() { public void getByteArrayBoundaryCheck1() {
buffer.getBytes(-1, EMPTY_ARRAY); buffer.getBytes(-1, EMPTY_BYTES);
} }
@Test(expected = IndexOutOfBoundsException.class) @Test(expected = IndexOutOfBoundsException.class)
public void getByteArrayBoundaryCheck2() { public void getByteArrayBoundaryCheck2() {
buffer.getBytes(-1, EMPTY_ARRAY, 0, 0); buffer.getBytes(-1, EMPTY_BYTES, 0, 0);
} }
@Test @Test

View File

@ -24,13 +24,13 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import static io.netty.buffer.Unpooled.*; import static io.netty.buffer.Unpooled.*;
import static io.netty.util.internal.EmptyArrays.*;
import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*; import static org.junit.Assert.*;
/** /**
* An abstract test class for composite channel buffers * An abstract test class for composite channel buffers
*/ */
@SuppressWarnings("ZeroLengthArrayAllocation")
public abstract class AbstractCompositeByteBufTest extends AbstractByteBufTest { public abstract class AbstractCompositeByteBufTest extends AbstractByteBufTest {
private final ByteOrder order; private final ByteOrder order;
@ -418,7 +418,7 @@ public abstract class AbstractCompositeByteBufTest extends AbstractByteBufTest {
public void testEmptyBuffer() { public void testEmptyBuffer() {
ByteBuf b = freeLater(wrappedBuffer(new byte[]{1, 2}, new byte[]{3, 4})); ByteBuf b = freeLater(wrappedBuffer(new byte[]{1, 2}, new byte[]{3, 4}));
b.readBytes(new byte[4]); b.readBytes(new byte[4]);
b.readBytes(new byte[0]); b.readBytes(EMPTY_BYTES);
} }
// Test for https://github.com/netty/netty/issues/1060 // Test for https://github.com/netty/netty/issues/1060

View File

@ -20,12 +20,12 @@ import org.junit.Test;
import java.io.EOFException; import java.io.EOFException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import static io.netty.util.internal.EmptyArrays.*;
import static org.junit.Assert.*; import static org.junit.Assert.*;
/** /**
* Tests channel buffer streams * Tests channel buffer streams
*/ */
@SuppressWarnings("ZeroLengthArrayAllocation")
public class ByteBufStreamTest { public class ByteBufStreamTest {
@Test @Test
@ -56,7 +56,7 @@ public class ByteBufStreamTest {
out.writeShort(49152); out.writeShort(49152);
out.writeUTF("Hello, World!"); out.writeUTF("Hello, World!");
out.writeBytes("The first line\r\r\n"); 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, 2, 3, 4 });
out.write(new byte[] { 1, 3, 3, 4 }, 0, 0); out.write(new byte[] { 1, 3, 3, 4 }, 0, 0);
out.close(); out.close();

View File

@ -31,14 +31,17 @@ import java.util.Map.Entry;
import java.util.Queue; import java.util.Queue;
import static io.netty.buffer.Unpooled.*; import static io.netty.buffer.Unpooled.*;
import static io.netty.util.internal.EmptyArrays.*;
import static org.junit.Assert.*; import static org.junit.Assert.*;
/** /**
* Tests channel buffers * Tests channel buffers
*/ */
@SuppressWarnings("ZeroLengthArrayAllocation")
public class UnpooledTest { 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<ByteBuf> freeLaterQueue = new ArrayDeque<ByteBuf>(); private static final Queue<ByteBuf> freeLaterQueue = new ArrayDeque<ByteBuf>();
protected ByteBuf freeLater(ByteBuf buf) { protected ByteBuf freeLater(ByteBuf buf) {
@ -82,7 +85,7 @@ public class UnpooledTest {
@Test @Test
public void testHashCode() { public void testHashCode() {
Map<byte[], Integer> map = new LinkedHashMap<byte[], Integer>(); Map<byte[], Integer> map = new LinkedHashMap<byte[], Integer>();
map.put(new byte[0], 1); map.put(EMPTY_BYTES, 1);
map.put(new byte[] { 1 }, 32); map.put(new byte[] { 1 }, 32);
map.put(new byte[] { 2 }, 33); map.put(new byte[] { 2 }, 33);
map.put(new byte[] { 0, 1 }, 962); map.put(new byte[] { 0, 1 }, 962);
@ -183,31 +186,31 @@ public class UnpooledTest {
@Test @Test
public void shouldReturnEmptyBufferWhenLengthIsZero() { 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], 0, 0));
assertSame(EMPTY_BUFFER, wrappedBuffer(new byte[8], 8, 0)); assertSame(EMPTY_BUFFER, wrappedBuffer(new byte[8], 8, 0));
assertSame(EMPTY_BUFFER, wrappedBuffer(ByteBuffer.allocateDirect(0))); assertSame(EMPTY_BUFFER, wrappedBuffer(ByteBuffer.allocateDirect(0)));
assertSame(EMPTY_BUFFER, wrappedBuffer(EMPTY_BUFFER)); assertSame(EMPTY_BUFFER, wrappedBuffer(EMPTY_BUFFER));
assertSame(EMPTY_BUFFER, wrappedBuffer(new byte[0][])); assertSame(EMPTY_BUFFER, wrappedBuffer(EMPTY_BYTES_2D));
assertSame(EMPTY_BUFFER, wrappedBuffer(new byte[][] { new byte[0] })); assertSame(EMPTY_BUFFER, wrappedBuffer(new byte[][] { EMPTY_BYTES }));
assertSame(EMPTY_BUFFER, wrappedBuffer(new ByteBuffer[0])); assertSame(EMPTY_BUFFER, wrappedBuffer(EMPTY_BYTE_BUFFERS));
assertSame(EMPTY_BUFFER, wrappedBuffer(new ByteBuffer[] { ByteBuffer.allocate(0) })); assertSame(EMPTY_BUFFER, wrappedBuffer(new ByteBuffer[] { ByteBuffer.allocate(0) }));
assertSame(EMPTY_BUFFER, wrappedBuffer(ByteBuffer.allocate(0), 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(new ByteBuf[] { buffer(0) }));
assertSame(EMPTY_BUFFER, wrappedBuffer(buffer(0), 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], 0, 0));
assertSame(EMPTY_BUFFER, copiedBuffer(new byte[8], 8, 0)); assertSame(EMPTY_BUFFER, copiedBuffer(new byte[8], 8, 0));
assertSame(EMPTY_BUFFER, copiedBuffer(ByteBuffer.allocateDirect(0))); assertSame(EMPTY_BUFFER, copiedBuffer(ByteBuffer.allocateDirect(0)));
assertSame(EMPTY_BUFFER, copiedBuffer(EMPTY_BUFFER)); assertSame(EMPTY_BUFFER, copiedBuffer(EMPTY_BUFFER));
assertSame(EMPTY_BUFFER, copiedBuffer(new byte[0][])); assertSame(EMPTY_BUFFER, copiedBuffer(EMPTY_BYTES_2D));
assertSame(EMPTY_BUFFER, copiedBuffer(new byte[][] { new byte[0] })); assertSame(EMPTY_BUFFER, copiedBuffer(new byte[][] { EMPTY_BYTES }));
assertSame(EMPTY_BUFFER, copiedBuffer(new ByteBuffer[0])); assertSame(EMPTY_BUFFER, copiedBuffer(EMPTY_BYTE_BUFFERS));
assertSame(EMPTY_BUFFER, copiedBuffer(new ByteBuffer[] { ByteBuffer.allocate(0) })); assertSame(EMPTY_BUFFER, copiedBuffer(new ByteBuffer[] { ByteBuffer.allocate(0) }));
assertSame(EMPTY_BUFFER, copiedBuffer(ByteBuffer.allocate(0), 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(new ByteBuf[] { buffer(0) }));
assertSame(EMPTY_BUFFER, copiedBuffer(buffer(0), buffer(0))); assertSame(EMPTY_BUFFER, copiedBuffer(buffer(0), buffer(0)));
} }
@ -370,7 +373,7 @@ public class UnpooledTest {
} }
try { try {
buf.setBytes(0, new byte[0], 0, 0); buf.setBytes(0, EMPTY_BYTES, 0, 0);
fail(); fail();
} catch (UnsupportedOperationException e) { } catch (UnsupportedOperationException e) {
// Expected // Expected
@ -443,7 +446,7 @@ public class UnpooledTest {
assertFalse(buffer.isReadable()); assertFalse(buffer.isReadable());
assertEquals(0, Unpooled.copyInt(null).capacity()); assertEquals(0, Unpooled.copyInt(null).capacity());
assertEquals(0, Unpooled.copyInt(new int[0]).capacity()); assertEquals(0, Unpooled.copyInt(EMPTY_INTS).capacity());
} }
@Test @Test
@ -463,7 +466,7 @@ public class UnpooledTest {
assertFalse(buffer.isReadable()); assertFalse(buffer.isReadable());
assertEquals(0, Unpooled.copyShort((short[]) null).capacity()); assertEquals(0, Unpooled.copyShort((short[]) null).capacity());
assertEquals(0, Unpooled.copyShort(new short[0]).capacity()); assertEquals(0, Unpooled.copyShort(EMPTY_SHORTS).capacity());
} }
@Test @Test
@ -475,7 +478,7 @@ public class UnpooledTest {
assertFalse(buffer.isReadable()); assertFalse(buffer.isReadable());
assertEquals(0, Unpooled.copyShort((int[]) null).capacity()); assertEquals(0, Unpooled.copyShort((int[]) null).capacity());
assertEquals(0, Unpooled.copyShort(new int[0]).capacity()); assertEquals(0, Unpooled.copyShort(EMPTY_INTS).capacity());
} }
@Test @Test
@ -495,7 +498,7 @@ public class UnpooledTest {
assertFalse(buffer.isReadable()); assertFalse(buffer.isReadable());
assertEquals(0, Unpooled.copyMedium(null).capacity()); assertEquals(0, Unpooled.copyMedium(null).capacity());
assertEquals(0, Unpooled.copyMedium(new int[0]).capacity()); assertEquals(0, Unpooled.copyMedium(EMPTY_INTS).capacity());
} }
@Test @Test
@ -515,7 +518,7 @@ public class UnpooledTest {
assertFalse(buffer.isReadable()); assertFalse(buffer.isReadable());
assertEquals(0, Unpooled.copyLong(null).capacity()); assertEquals(0, Unpooled.copyLong(null).capacity());
assertEquals(0, Unpooled.copyLong(new long[0]).capacity()); assertEquals(0, Unpooled.copyLong(EMPTY_LONGS).capacity());
} }
@Test @Test
@ -535,7 +538,7 @@ public class UnpooledTest {
assertFalse(buffer.isReadable()); assertFalse(buffer.isReadable());
assertEquals(0, Unpooled.copyFloat(null).capacity()); assertEquals(0, Unpooled.copyFloat(null).capacity());
assertEquals(0, Unpooled.copyFloat(new float[0]).capacity()); assertEquals(0, Unpooled.copyFloat(EMPTY_FLOATS).capacity());
} }
@Test @Test
@ -555,7 +558,7 @@ public class UnpooledTest {
assertFalse(buffer.isReadable()); assertFalse(buffer.isReadable());
assertEquals(0, Unpooled.copyDouble(null).capacity()); assertEquals(0, Unpooled.copyDouble(null).capacity());
assertEquals(0, Unpooled.copyDouble(new double[0]).capacity()); assertEquals(0, Unpooled.copyDouble(EMPTY_DOUBLES).capacity());
} }
@Test @Test
@ -567,7 +570,7 @@ public class UnpooledTest {
assertFalse(buffer.isReadable()); assertFalse(buffer.isReadable());
assertEquals(0, Unpooled.copyBoolean(null).capacity()); assertEquals(0, Unpooled.copyBoolean(null).capacity());
assertEquals(0, Unpooled.copyBoolean(new boolean[0]).capacity()); assertEquals(0, Unpooled.copyBoolean(EMPTY_BOOLEANS).capacity());
} }
@Test @Test

View File

@ -17,6 +17,7 @@ package io.netty.handler.codec.http.multipart;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.http.HttpConstants; import io.netty.handler.codec.http.HttpConstants;
import io.netty.util.internal.EmptyArrays;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
@ -222,7 +223,7 @@ public abstract class AbstractDiskHttpData extends AbstractHttpData {
@Override @Override
public byte[] get() throws IOException { public byte[] get() throws IOException {
if (file == null) { if (file == null) {
return new byte[0]; return EmptyArrays.EMPTY_BYTES;
} }
return readFrom(file); return readFrom(file);
} }

View File

@ -18,14 +18,13 @@ package io.netty.handler.codec.http.websocketx;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import io.netty.util.CharsetUtil; import io.netty.util.CharsetUtil;
import io.netty.util.internal.EmptyArrays;
/** /**
* Web Socket Frame for closing the connection * Web Socket Frame for closing the connection
*/ */
public class CloseWebSocketFrame extends WebSocketFrame { public class CloseWebSocketFrame extends WebSocketFrame {
private static final byte[] EMTPY_REASON = new byte[0];
/** /**
* Creates a new empty close frame. * Creates a new empty close frame.
*/ */
@ -76,7 +75,7 @@ public class CloseWebSocketFrame extends WebSocketFrame {
} }
private static ByteBuf newBinaryData(int statusCode, String reasonText) { private static ByteBuf newBinaryData(int statusCode, String reasonText) {
byte[] reasonBytes = EMTPY_REASON; byte[] reasonBytes = EmptyArrays.EMPTY_BYTES;
if (reasonText != null) { if (reasonText != null) {
reasonBytes = reasonText.getBytes(CharsetUtil.UTF_8); reasonBytes = reasonText.getBytes(CharsetUtil.UTF_8);
} }

View File

@ -30,6 +30,7 @@ import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequestDecoder; import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder; import io.netty.handler.codec.http.HttpResponseEncoder;
import io.netty.handler.codec.http.HttpServerCodec; import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.util.internal.EmptyArrays;
import io.netty.util.internal.StringUtil; import io.netty.util.internal.StringUtil;
import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory; import io.netty.util.internal.logging.InternalLoggerFactory;
@ -44,8 +45,6 @@ import java.util.Set;
public abstract class WebSocketServerHandshaker { public abstract class WebSocketServerHandshaker {
protected static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocketServerHandshaker.class); 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 uri;
private final String[] subprotocols; private final String[] subprotocols;
@ -81,7 +80,7 @@ public abstract class WebSocketServerHandshaker {
} }
this.subprotocols = subprotocolArray; this.subprotocols = subprotocolArray;
} else { } else {
this.subprotocols = EMPTY_ARRAY; this.subprotocols = EmptyArrays.EMPTY_STRINGS;
} }
this.maxFramePayloadLength = maxFramePayloadLength; this.maxFramePayloadLength = maxFramePayloadLength;
} }

View File

@ -24,6 +24,7 @@ import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundMessageHandler; import io.netty.channel.ChannelInboundMessageHandler;
import io.netty.channel.ChannelOutboundMessageHandler; import io.netty.channel.ChannelOutboundMessageHandler;
import io.netty.channel.ChannelPromise; import io.netty.channel.ChannelPromise;
import io.netty.util.internal.EmptyArrays;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@ -38,10 +39,8 @@ public class SpdySessionHandler
private static final SpdyProtocolException STREAM_CLOSED = new SpdyProtocolException("Stream closed"); private static final SpdyProtocolException STREAM_CLOSED = new SpdyProtocolException("Stream closed");
static { static {
@SuppressWarnings("ZeroLengthArrayAllocation") PROTOCOL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
StackTraceElement[] emptyTrace = new StackTraceElement[0]; STREAM_CLOSED.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
PROTOCOL_EXCEPTION.setStackTrace(emptyTrace);
STREAM_CLOSED.setStackTrace(emptyTrace);
} }
private final SpdySession spdySession = new SpdySession(); private final SpdySession spdySession = new SpdySession();

View File

@ -23,6 +23,7 @@ import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise; import io.netty.channel.ChannelPromise;
import io.netty.util.internal.EmptyArrays;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@ -33,8 +34,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
*/ */
public class JZlibEncoder extends ZlibEncoder { public class JZlibEncoder extends ZlibEncoder {
private static final byte[] EMPTY_ARRAY = new byte[0];
private final Deflater z = new Deflater(); private final Deflater z = new Deflater();
private final AtomicBoolean finished = new AtomicBoolean(); private final AtomicBoolean finished = new AtomicBoolean();
private volatile ChannelHandlerContext ctx; private volatile ChannelHandlerContext ctx;
@ -367,7 +366,7 @@ public class JZlibEncoder extends ZlibEncoder {
synchronized (z) { synchronized (z) {
try { try {
// Configure input. // Configure input.
z.next_in = EMPTY_ARRAY; z.next_in = EmptyArrays.EMPTY_BYTES;
z.next_in_index = 0; z.next_in_index = 0;
z.avail_in = 0; z.avail_in = 0;

View File

@ -16,6 +16,7 @@
package io.netty.handler.codec.bytes; package io.netty.handler.codec.bytes;
import io.netty.channel.embedded.EmbeddedMessageChannel; import io.netty.channel.embedded.EmbeddedMessageChannel;
import io.netty.util.internal.EmptyArrays;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -48,7 +49,7 @@ public class ByteArrayDecoderTest {
@Test @Test
public void testDecodeEmpty() { public void testDecodeEmpty() {
ch.writeInbound(EMPTY_BUFFER); ch.writeInbound(EMPTY_BUFFER);
assertThat((byte[]) ch.readInbound(), is(new byte[0])); assertThat((byte[]) ch.readInbound(), is(EmptyArrays.EMPTY_BYTES));
} }
@Test @Test

View File

@ -17,6 +17,7 @@ package io.netty.handler.codec.bytes;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.channel.embedded.EmbeddedMessageChannel; import io.netty.channel.embedded.EmbeddedMessageChannel;
import io.netty.util.internal.EmptyArrays;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -47,8 +48,7 @@ public class ByteArrayEncoderTest {
@Test @Test
public void testEncodeEmpty() { public void testEncodeEmpty() {
byte[] b = new byte[0]; ch.writeOutbound(EmptyArrays.EMPTY_BYTES);
ch.writeOutbound(b);
assertThat(ch.readOutbound(), nullValue()); assertThat(ch.readOutbound(), nullValue());
} }

View File

@ -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() { }
}

View File

@ -35,6 +35,7 @@ import io.netty.util.concurrent.EventExecutor;
import io.netty.util.concurrent.Future; import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener; import io.netty.util.concurrent.GenericFutureListener;
import io.netty.util.concurrent.ImmediateExecutor; import io.netty.util.concurrent.ImmediateExecutor;
import io.netty.util.internal.EmptyArrays;
import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory; import io.netty.util.internal.logging.InternalLoggerFactory;
@ -163,6 +164,16 @@ public class SslHandler
"^.*(?:connection.*reset|connection.*closed|broken.*pipe).*$", "^.*(?:connection.*reset|connection.*closed|broken.*pipe).*$",
Pattern.CASE_INSENSITIVE); 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 volatile ChannelHandlerContext ctx;
private final SSLEngine engine; private final SSLEngine engine;
private final Executor delegatedTaskExecutor; private final Executor delegatedTaskExecutor;
@ -479,10 +490,9 @@ public class SslHandler
// Any further write attempts should be denied. // Any further write attempts should be denied.
if (in.isReadable()) { if (in.isReadable()) {
in.clear(); in.clear();
SSLException e = new SSLException("SSLEngine already closed"); promise.setFailure(SSLENGINE_CLOSED);
promise.setFailure(e); ctx.fireExceptionCaught(SSLENGINE_CLOSED);
ctx.fireExceptionCaught(e); flush0(ctx, bytesConsumed, SSLENGINE_CLOSED);
flush0(ctx, bytesConsumed, e);
bytesConsumed = 0; bytesConsumed = 0;
} }
break; break;
@ -597,9 +607,9 @@ public class SslHandler
@Override @Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception { public void channelInactive(ChannelHandlerContext ctx) throws Exception {
// Make sure the handshake future is notified when a connection has // Make sure to release SSLEngine,
// been closed during handshake. // and notify the handshake future if the connection has been closed during handshake.
setHandshakeFailure(new ClosedChannelException()); setHandshakeFailure(CHANNEL_CLOSED);
try { try {
inboundBufferUpdated(ctx); inboundBufferUpdated(ctx);
@ -983,9 +993,8 @@ public class SslHandler
return; return;
} }
SSLException e = new SSLException("handshake timed out"); if (handshakePromise.tryFailure(HANDSHAKE_TIMED_OUT)) {
if (handshakePromise.tryFailure(e)) { ctx.fireExceptionCaught(HANDSHAKE_TIMED_OUT);
ctx.fireExceptionCaught(e);
ctx.close(); ctx.close();
} }
} }

View File

@ -18,6 +18,7 @@ package io.netty.channel;
import io.netty.util.concurrent.AbstractEventExecutorGroup; import io.netty.util.concurrent.AbstractEventExecutorGroup;
import io.netty.util.concurrent.EventExecutor; import io.netty.util.concurrent.EventExecutor;
import io.netty.util.internal.EmptyArrays;
import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.ReadOnlyIterator; import io.netty.util.internal.ReadOnlyIterator;
@ -35,9 +36,6 @@ import java.util.concurrent.TimeUnit;
*/ */
public class ThreadPerChannelEventLoopGroup extends AbstractEventExecutorGroup implements EventLoopGroup { 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 Object[] childArgs;
private final int maxChannels; private final int maxChannels;
final ThreadFactory threadFactory; final ThreadFactory threadFactory;
@ -88,7 +86,7 @@ public class ThreadPerChannelEventLoopGroup extends AbstractEventExecutorGroup i
} }
if (args == null) { if (args == null) {
childArgs = NO_ARGS; childArgs = EmptyArrays.EMPTY_OBJECTS;
} else { } else {
childArgs = args.clone(); childArgs = args.clone();
} }
@ -97,7 +95,7 @@ public class ThreadPerChannelEventLoopGroup extends AbstractEventExecutorGroup i
this.threadFactory = threadFactory; this.threadFactory = threadFactory;
tooManyChannels = new ChannelException("too many channels (max: " + maxChannels + ')'); tooManyChannels = new ChannelException("too many channels (max: " + maxChannels + ')');
tooManyChannels.setStackTrace(STACK_ELEMENTS); tooManyChannels.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
} }
/** /**

View File

@ -27,6 +27,7 @@ import io.netty.channel.socket.DatagramChannel;
import io.netty.channel.socket.DatagramChannelConfig; import io.netty.channel.socket.DatagramChannelConfig;
import io.netty.channel.socket.DatagramPacket; import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.DefaultDatagramChannelConfig; import io.netty.channel.socket.DefaultDatagramChannelConfig;
import io.netty.util.internal.EmptyArrays;
import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory; 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 ChannelMetadata METADATA = new ChannelMetadata(BufType.MESSAGE, true);
private static final byte[] EMPTY_DATA = new byte[0];
private final MulticastSocket socket; private final MulticastSocket socket;
private final DatagramChannelConfig config; 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() { private static MulticastSocket newSocket() {
try { try {