From 3719b5f9198e8b92d73ea80468cfbe1e4170a1c7 Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Thu, 9 Jun 2016 13:29:59 +0200 Subject: [PATCH] Set some StackTraceElement on pre-instantiated static exceptions Motivation: We use pre-instantiated exceptions in various places for performance reasons. These exceptions don't include a stacktrace which makes it hard to know where the exception was thrown. This is especially true as we use the same exception type (for example ChannelClosedException) in different places. Setting some StackTraceElements will provide more context as to where these exceptions original and make debugging easier. Modifications: Set a generated StackTraceElement on these pre-instantiated exceptions which at least contains the origin class and method name. The filename and linenumber are specified as unkown (as stated in the javadocs of StackTraceElement). Result: Easier to find the origin of a pre-instantiated exception. --- .../websocketx/WebSocketClientHandshaker.java | 9 ++-- .../websocketx/WebSocketServerHandshaker.java | 8 ++- .../codec/spdy/SpdySessionHandler.java | 13 ++--- .../netty/util/concurrent/DefaultPromise.java | 6 +-- .../io/netty/util/internal/ThrowableUtil.java | 29 +++++++++++ .../io/netty/handler/ssl/OpenSslEngine.java | 24 +++++---- .../java/io/netty/handler/ssl/SslHandler.java | 17 +++--- .../epoll/AbstractEpollStreamChannel.java | 28 ++++++---- .../java/io/netty/channel/epoll/Native.java | 26 ++++++---- .../java/io/netty/channel/unix/Errors.java | 30 ++--------- .../io/netty/channel/unix/FileDescriptor.java | 52 +++++++++++++++---- .../java/io/netty/channel/unix/Socket.java | 35 ++++++++++--- .../io/netty/channel/AbstractChannel.java | 39 ++++++++------ .../ThreadPerChannelEventLoopGroup.java | 6 ++- .../io/netty/channel/local/LocalChannel.java | 14 ++--- .../netty/channel/nio/AbstractNioChannel.java | 11 ++-- .../netty/channel/pool/FixedChannelPool.java | 17 +++--- .../netty/channel/pool/SimpleChannelPool.java | 15 +++--- 18 files changed, 223 insertions(+), 156 deletions(-) create mode 100644 common/src/main/java/io/netty/util/internal/ThrowableUtil.java diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker.java index e15e373672..713e08cf87 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker.java @@ -32,8 +32,8 @@ import io.netty.handler.codec.http.HttpRequestEncoder; import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseDecoder; import io.netty.util.ReferenceCountUtil; -import io.netty.util.internal.EmptyArrays; import io.netty.util.internal.StringUtil; +import io.netty.util.internal.ThrowableUtil; import java.net.URI; import java.nio.channels.ClosedChannelException; @@ -42,11 +42,8 @@ import java.nio.channels.ClosedChannelException; * Base class for web socket client handshake implementations */ public abstract class WebSocketClientHandshaker { - private static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION = new ClosedChannelException(); - - static { - CLOSED_CHANNEL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - } + private static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace( + new ClosedChannelException(), WebSocketClientHandshaker.class, "processHandshake(...)"); private final URI uri; 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 09dc546c89..00c54fe919 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 @@ -34,6 +34,7 @@ import io.netty.handler.codec.http.HttpServerCodec; import io.netty.util.ReferenceCountUtil; import io.netty.util.internal.EmptyArrays; import io.netty.util.internal.StringUtil; +import io.netty.util.internal.ThrowableUtil; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; @@ -47,11 +48,8 @@ import java.util.Set; */ public abstract class WebSocketServerHandshaker { protected static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocketServerHandshaker.class); - private static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION = new ClosedChannelException(); - - static { - CLOSED_CHANNEL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - } + private static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace( + new ClosedChannelException(), WebSocketServerHandshaker.class, "handshake(...)"); private final String uri; 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 338456be5a..a3d3636f0e 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 @@ -20,7 +20,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 io.netty.util.internal.ThrowableUtil; import java.util.concurrent.atomic.AtomicInteger; @@ -32,13 +32,10 @@ import static io.netty.handler.codec.spdy.SpdyCodecUtil.*; public class SpdySessionHandler extends ChannelDuplexHandler { - private static final SpdyProtocolException PROTOCOL_EXCEPTION = new SpdyProtocolException(); - private static final SpdyProtocolException STREAM_CLOSED = new SpdyProtocolException("Stream closed"); - - static { - PROTOCOL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - STREAM_CLOSED.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - } + private static final SpdyProtocolException PROTOCOL_EXCEPTION = ThrowableUtil.unknownStackTrace( + new SpdyProtocolException(), SpdySessionHandler.class, "handleOutboundMessage(...)"); + private static final SpdyProtocolException STREAM_CLOSED = ThrowableUtil.unknownStackTrace( + new SpdyProtocolException("Stream closed"), SpdySessionHandler.class, "removeStream(...)"); private static final int DEFAULT_WINDOW_SIZE = 64 * 1024; // 64 KB default initial window size private int initialSendWindowSize = DEFAULT_WINDOW_SIZE; diff --git a/common/src/main/java/io/netty/util/concurrent/DefaultPromise.java b/common/src/main/java/io/netty/util/concurrent/DefaultPromise.java index f1c11c53ad..a4380bb439 100644 --- a/common/src/main/java/io/netty/util/concurrent/DefaultPromise.java +++ b/common/src/main/java/io/netty/util/concurrent/DefaultPromise.java @@ -16,10 +16,10 @@ package io.netty.util.concurrent; import io.netty.util.Signal; -import io.netty.util.internal.EmptyArrays; import io.netty.util.internal.InternalThreadLocalMap; import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.StringUtil; +import io.netty.util.internal.ThrowableUtil; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; @@ -39,7 +39,8 @@ public class DefaultPromise extends AbstractFuture implements Promise { private static final AtomicReferenceFieldUpdater RESULT_UPDATER; private static final Signal SUCCESS = Signal.valueOf(DefaultPromise.class.getName() + ".SUCCESS"); private static final Signal UNCANCELLABLE = Signal.valueOf(DefaultPromise.class.getName() + ".UNCANCELLABLE"); - private static final CauseHolder CANCELLATION_CAUSE_HOLDER = new CauseHolder(new CancellationException()); + private static final CauseHolder CANCELLATION_CAUSE_HOLDER = new CauseHolder(ThrowableUtil.unknownStackTrace( + new CancellationException(), DefaultPromise.class, "cancel(...)")); static { @SuppressWarnings("rawtypes") @@ -47,7 +48,6 @@ public class DefaultPromise extends AbstractFuture implements Promise { PlatformDependent.newAtomicReferenceFieldUpdater(DefaultPromise.class, "result"); RESULT_UPDATER = updater == null ? AtomicReferenceFieldUpdater.newUpdater(DefaultPromise.class, Object.class, "result") : updater; - CANCELLATION_CAUSE_HOLDER.cause.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); } private volatile Object result; diff --git a/common/src/main/java/io/netty/util/internal/ThrowableUtil.java b/common/src/main/java/io/netty/util/internal/ThrowableUtil.java new file mode 100644 index 0000000000..790196b9c2 --- /dev/null +++ b/common/src/main/java/io/netty/util/internal/ThrowableUtil.java @@ -0,0 +1,29 @@ +/* + * Copyright 2016 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; + +public final class ThrowableUtil { + + private ThrowableUtil() { } + + /** + * Set the {@link StackTraceElement} for the given {@link Throwable}, using the {@link Class} and method name. + */ + public static T unknownStackTrace(T cause, Class clazz, String method) { + cause.setStackTrace(new StackTraceElement[] { new StackTraceElement(clazz.getName(), method, null, -1)}); + return cause; + } +} diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslEngine.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslEngine.java index 9a074fd744..c65fbea484 100644 --- a/handler/src/main/java/io/netty/handler/ssl/OpenSslEngine.java +++ b/handler/src/main/java/io/netty/handler/ssl/OpenSslEngine.java @@ -22,6 +22,7 @@ import io.netty.util.internal.EmptyArrays; import io.netty.util.internal.InternalThreadLocalMap; import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.StringUtil; +import io.netty.util.internal.ThrowableUtil; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; import org.apache.tomcat.jni.Buffer; @@ -78,9 +79,14 @@ public final class OpenSslEngine extends SSLEngine { private static final Certificate[] EMPTY_CERTIFICATES = EmptyArrays.EMPTY_CERTIFICATES; private static final X509Certificate[] EMPTY_X509_CERTIFICATES = EmptyArrays.EMPTY_JAVAX_X509_CERTIFICATES; - private static final SSLException ENGINE_CLOSED = new SSLException("engine closed"); - private static final SSLException RENEGOTIATION_UNSUPPORTED = new SSLException("renegotiation unsupported"); - private static final SSLException ENCRYPTED_PACKET_OVERSIZED = new SSLException("encrypted packet oversized"); + private static final SSLException BEGIN_HANDSHAKE_ENGINE_CLOSED = ThrowableUtil.unknownStackTrace( + new SSLException("engine closed"), OpenSslEngine.class, "beginHandshake()"); + private static final SSLException HANDSHAKE_ENGINE_CLOSED = ThrowableUtil.unknownStackTrace( + new SSLException("engine closed"), OpenSslEngine.class, "handshake()"); + private static final SSLException RENEGOTIATION_UNSUPPORTED = ThrowableUtil.unknownStackTrace( + new SSLException("renegotiation unsupported"), OpenSslEngine.class, "beginHandshake()"); + private static final SSLException ENCRYPTED_PACKET_OVERSIZED = ThrowableUtil.unknownStackTrace( + new SSLException("encrypted packet oversized"), OpenSslEngine.class, "unwrap(...)"); private static final Class SNI_HOSTNAME_CLASS; private static final Method GET_SERVER_NAMES_METHOD; private static final Method SET_SERVER_NAMES_METHOD; @@ -89,10 +95,6 @@ public final class OpenSslEngine extends SSLEngine { private static final Method SET_USE_CIPHER_SUITES_ORDER_METHOD; static { - ENGINE_CLOSED.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - RENEGOTIATION_UNSUPPORTED.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - ENCRYPTED_PACKET_OVERSIZED.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - AtomicIntegerFieldUpdater destroyedUpdater = PlatformDependent.newAtomicIntegerFieldUpdater(OpenSslEngine.class, "destroyed"); if (destroyedUpdater == null) { @@ -1208,7 +1210,7 @@ public final class OpenSslEngine extends SSLEngine { public synchronized void beginHandshake() throws SSLException { switch (handshakeState) { case STARTED_IMPLICITLY: - checkEngineClosed(); + checkEngineClosed(BEGIN_HANDSHAKE_ENGINE_CLOSED); // A user did not start handshake by calling this method by him/herself, // but handshake has been started already by wrap() or unwrap() implicitly. @@ -1255,9 +1257,9 @@ public final class OpenSslEngine extends SSLEngine { } } - private void checkEngineClosed() throws SSLException { + private void checkEngineClosed(SSLException cause) throws SSLException { if (engineClosed || isDestroyed()) { - throw ENGINE_CLOSED; + throw cause; } } @@ -1270,7 +1272,7 @@ public final class OpenSslEngine extends SSLEngine { if (handshakeState == HandshakeState.FINISHED) { return FINISHED; } - checkEngineClosed(); + checkEngineClosed(HANDSHAKE_ENGINE_CLOSED); // Check if we have a pending handshakeException and if so see if we need to consume all pending data from the // BIO first or can just shutdown and throw it now. 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 8b0abff358..c2db7a6c99 100644 --- a/handler/src/main/java/io/netty/handler/ssl/SslHandler.java +++ b/handler/src/main/java/io/netty/handler/ssl/SslHandler.java @@ -40,8 +40,8 @@ import io.netty.util.concurrent.Future; import io.netty.util.concurrent.FutureListener; import io.netty.util.concurrent.ImmediateExecutor; import io.netty.util.concurrent.Promise; -import io.netty.util.internal.EmptyArrays; import io.netty.util.internal.PlatformDependent; +import io.netty.util.internal.ThrowableUtil; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; @@ -177,15 +177,12 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH * {@link #unwrap(ChannelHandlerContext, ByteBuf, int, int)}. Using this static instance reduce object * creation as {@link Unpooled#EMPTY_BUFFER#nioBuffer()} creates a new {@link ByteBuffer} everytime. */ - 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 static final SSLException SSLENGINE_CLOSED = ThrowableUtil.unknownStackTrace( + new SSLException("SSLEngine closed already"), SslHandler.class, "wrap(...)"); + private static final SSLException HANDSHAKE_TIMED_OUT = ThrowableUtil.unknownStackTrace( + new SSLException("handshake timed out"), SslHandler.class, "handshake(...)"); + private static final ClosedChannelException CHANNEL_CLOSED = ThrowableUtil.unknownStackTrace( + new ClosedChannelException(), SslHandler.class, "channelInactive(...)"); private volatile ChannelHandlerContext ctx; private final SSLEngine engine; diff --git a/transport-native-epoll/src/main/java/io/netty/channel/epoll/AbstractEpollStreamChannel.java b/transport-native-epoll/src/main/java/io/netty/channel/epoll/AbstractEpollStreamChannel.java index c33429e2e9..3bc16d5403 100644 --- a/transport-native-epoll/src/main/java/io/netty/channel/epoll/AbstractEpollStreamChannel.java +++ b/transport-native-epoll/src/main/java/io/netty/channel/epoll/AbstractEpollStreamChannel.java @@ -32,9 +32,9 @@ import io.netty.channel.RecvByteBufAllocator; import io.netty.channel.socket.DuplexChannel; import io.netty.channel.unix.FileDescriptor; import io.netty.channel.unix.Socket; -import io.netty.util.internal.EmptyArrays; import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.StringUtil; +import io.netty.util.internal.ThrowableUtil; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; @@ -56,11 +56,17 @@ public abstract class AbstractEpollStreamChannel extends AbstractEpollChannel im " (expected: " + StringUtil.simpleClassName(ByteBuf.class) + ", " + StringUtil.simpleClassName(DefaultFileRegion.class) + ')'; private static final InternalLogger logger = InternalLoggerFactory.getInstance(AbstractEpollStreamChannel.class); - static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION = new ClosedChannelException(); - - static { - CLOSED_CHANNEL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - } + private static final ClosedChannelException DO_CLOSE_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace( + new ClosedChannelException(), AbstractEpollStreamChannel.class, "doClose()"); + private static final ClosedChannelException CLEAR_SPLICE_QUEUE_CLOSED_CHANNEL_EXCEPTION = + ThrowableUtil.unknownStackTrace(new ClosedChannelException(), + AbstractEpollStreamChannel.class, "clearSpliceQueue()"); + private static final ClosedChannelException SPLICE_TO_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace( + new ClosedChannelException(), + AbstractEpollStreamChannel.class, "spliceTo(...)"); + private static final ClosedChannelException FAIL_SPLICE_IF_CLOSED_CLOSED_CHANNEL_EXCEPTION = + ThrowableUtil.unknownStackTrace(new ClosedChannelException(), + AbstractEpollStreamChannel.class, "failSpliceIfClosed(...)"); /** * The future of the current connection attempt. If not null, subsequent @@ -170,7 +176,7 @@ public abstract class AbstractEpollStreamChannel extends AbstractEpollChannel im } checkNotNull(promise, "promise"); if (!isOpen()) { - promise.tryFailure(CLOSED_CHANNEL_EXCEPTION); + promise.tryFailure(SPLICE_TO_CLOSED_CHANNEL_EXCEPTION); } else { addToSpliceQueue(new SpliceInChannelTask(ch, len, promise)); failSpliceIfClosed(promise); @@ -223,7 +229,7 @@ public abstract class AbstractEpollStreamChannel extends AbstractEpollChannel im } checkNotNull(promise, "promise"); if (!isOpen()) { - promise.tryFailure(CLOSED_CHANNEL_EXCEPTION); + promise.tryFailure(SPLICE_TO_CLOSED_CHANNEL_EXCEPTION); } else { addToSpliceQueue(new SpliceFdTask(ch, offset, len, promise)); failSpliceIfClosed(promise); @@ -235,7 +241,7 @@ public abstract class AbstractEpollStreamChannel extends AbstractEpollChannel im if (!isOpen()) { // Seems like the Channel was closed in the meantime try to fail the promise to prevent any // cases where a future may not be notified otherwise. - if (promise.tryFailure(CLOSED_CHANNEL_EXCEPTION)) { + if (promise.tryFailure(FAIL_SPLICE_IF_CLOSED_CLOSED_CHANNEL_EXCEPTION)) { eventLoop().execute(new Runnable() { @Override public void run() { @@ -584,7 +590,7 @@ public abstract class AbstractEpollStreamChannel extends AbstractEpollChannel im ChannelPromise promise = connectPromise; if (promise != null) { // Use tryFailure() instead of setFailure() to avoid the race against cancel(). - promise.tryFailure(CLOSED_CHANNEL_EXCEPTION); + promise.tryFailure(DO_CLOSE_CLOSED_CHANNEL_EXCEPTION); connectPromise = null; } @@ -611,7 +617,7 @@ public abstract class AbstractEpollStreamChannel extends AbstractEpollChannel im if (task == null) { break; } - task.promise.tryFailure(CLOSED_CHANNEL_EXCEPTION); + task.promise.tryFailure(CLEAR_SPLICE_QUEUE_CLOSED_CHANNEL_EXCEPTION); } } diff --git a/transport-native-epoll/src/main/java/io/netty/channel/epoll/Native.java b/transport-native-epoll/src/main/java/io/netty/channel/epoll/Native.java index d9244314fb..215ffaa165 100644 --- a/transport-native-epoll/src/main/java/io/netty/channel/epoll/Native.java +++ b/transport-native-epoll/src/main/java/io/netty/channel/epoll/Native.java @@ -22,9 +22,11 @@ import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.SystemPropertyUtil; import io.netty.channel.unix.FileDescriptor; import io.netty.channel.unix.NativeInetAddress; +import io.netty.util.internal.ThrowableUtil; import java.io.IOException; import java.net.InetAddress; +import java.nio.channels.ClosedChannelException; import java.util.Locale; import static io.netty.channel.epoll.NativeStaticallyReferencedJniMethods.epollerr; @@ -78,16 +80,22 @@ public final class Native { public static final int TCP_MD5SIG_MAXKEYLEN = tcpMd5SigMaxKeyLen(); public static final String KERNEL_VERSION = kernelVersion(); - private static final NativeIoException CONNECTION_RESET_EXCEPTION_SENDFILE; - private static final NativeIoException CONNECTION_RESET_EXCEPTION_SENDMMSG; - private static final NativeIoException CONNECTION_RESET_EXCEPTION_SPLICE; + private static final NativeIoException SENDFILE_CONNECTION_RESET_EXCEPTION; + private static final NativeIoException SENDMMSG_CONNECTION_RESET_EXCEPTION; + private static final NativeIoException SPLICE_CONNECTION_RESET_EXCEPTION; + private static final ClosedChannelException SENDFILE_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace( + new ClosedChannelException(), Native.class, "sendfile(...)"); + private static final ClosedChannelException SENDMMSG_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace( + new ClosedChannelException(), Native.class, "sendmmsg(...)"); + private static final ClosedChannelException SPLICE_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace( + new ClosedChannelException(), Native.class, "splice(...)"); static { - CONNECTION_RESET_EXCEPTION_SENDFILE = newConnectionResetException("syscall:sendfile(...)", + SENDFILE_CONNECTION_RESET_EXCEPTION = newConnectionResetException("syscall:sendfile(...)", ERRNO_EPIPE_NEGATIVE); - CONNECTION_RESET_EXCEPTION_SENDMMSG = newConnectionResetException("syscall:sendmmsg(...)", + SENDMMSG_CONNECTION_RESET_EXCEPTION = newConnectionResetException("syscall:sendmmsg(...)", ERRNO_EPIPE_NEGATIVE); - CONNECTION_RESET_EXCEPTION_SPLICE = newConnectionResetException("syscall:splice(...)", + SPLICE_CONNECTION_RESET_EXCEPTION = newConnectionResetException("syscall:splice(...)", ERRNO_EPIPE_NEGATIVE); } @@ -144,7 +152,7 @@ public final class Native { if (res >= 0) { return res; } - return ioResult("splice", res, CONNECTION_RESET_EXCEPTION_SPLICE); + return ioResult("splice", res, SPLICE_CONNECTION_RESET_EXCEPTION, SPLICE_CLOSED_CHANNEL_EXCEPTION); } private static native int splice0(int fd, long offIn, int fdOut, long offOut, long len); @@ -159,7 +167,7 @@ public final class Native { if (res >= 0) { return res; } - return ioResult("sendfile", (int) res, CONNECTION_RESET_EXCEPTION_SENDFILE); + return ioResult("sendfile", (int) res, SENDFILE_CONNECTION_RESET_EXCEPTION, SENDFILE_CLOSED_CHANNEL_EXCEPTION); } private static native long sendfile0( @@ -171,7 +179,7 @@ public final class Native { if (res >= 0) { return res; } - return ioResult("sendmmsg", res, CONNECTION_RESET_EXCEPTION_SENDMMSG); + return ioResult("sendmmsg", res, SENDMMSG_CONNECTION_RESET_EXCEPTION, SENDMMSG_CLOSED_CHANNEL_EXCEPTION); } private static native int sendmmsg0( diff --git a/transport-native-epoll/src/main/java/io/netty/channel/unix/Errors.java b/transport-native-epoll/src/main/java/io/netty/channel/unix/Errors.java index 8f00c9a870..d0f0b7d165 100644 --- a/transport-native-epoll/src/main/java/io/netty/channel/unix/Errors.java +++ b/transport-native-epoll/src/main/java/io/netty/channel/unix/Errors.java @@ -53,16 +53,6 @@ public final class Errors { */ private static final String[] ERRORS = new String[512]; - // Pre-instantiated exceptions which does not need any stacktrace and - // can be thrown multiple times for performance reasons. - static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION; - static final NativeIoException CONNECTION_NOT_CONNECTED_SHUTDOWN_EXCEPTION; - static final NativeIoException CONNECTION_RESET_EXCEPTION_WRITE; - static final NativeIoException CONNECTION_RESET_EXCEPTION_WRITEV; - static final NativeIoException CONNECTION_RESET_EXCEPTION_READ; - static final NativeIoException CONNECTION_RESET_EXCEPTION_SENDTO; - static final NativeIoException CONNECTION_RESET_EXCEPTION_SENDMSG; - /** * Internal usage only! */ @@ -84,21 +74,6 @@ public final class Errors { // This is ok as strerror returns 'Unknown error i' when the message is not known. ERRORS[i] = strError(i); } - - CONNECTION_RESET_EXCEPTION_READ = newConnectionResetException("syscall:read(...)", - ERRNO_ECONNRESET_NEGATIVE); - CONNECTION_RESET_EXCEPTION_WRITE = newConnectionResetException("syscall:write(...)", - ERRNO_EPIPE_NEGATIVE); - CONNECTION_RESET_EXCEPTION_WRITEV = newConnectionResetException("syscall:writev(...)", - ERRNO_EPIPE_NEGATIVE); - CONNECTION_RESET_EXCEPTION_SENDTO = newConnectionResetException("syscall:sendto(...)", - ERRNO_EPIPE_NEGATIVE); - CONNECTION_RESET_EXCEPTION_SENDMSG = newConnectionResetException("syscall:sendmsg(...)", - ERRNO_EPIPE_NEGATIVE); - CONNECTION_NOT_CONNECTED_SHUTDOWN_EXCEPTION = newConnectionResetException("syscall:shutdown(...)", - ERRNO_ENOTCONN_NEGATIVE); - CLOSED_CHANNEL_EXCEPTION = new ClosedChannelException(); - CLOSED_CHANNEL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); } static ConnectException newConnectException(String method, int err) { @@ -115,7 +90,8 @@ public final class Errors { return new NativeIoException(method + "() failed: " + ERRORS[-err], err); } - public static int ioResult(String method, int err, NativeIoException resetCause) throws IOException { + public static int ioResult(String method, int err, NativeIoException resetCause, + ClosedChannelException closedCause) throws IOException { // network stack saturated... try again later if (err == ERRNO_EAGAIN_NEGATIVE || err == ERRNO_EWOULDBLOCK_NEGATIVE) { return 0; @@ -124,7 +100,7 @@ public final class Errors { throw resetCause; } if (err == ERRNO_EBADF_NEGATIVE || err == ERRNO_ENOTCONN_NEGATIVE) { - throw CLOSED_CHANNEL_EXCEPTION; + throw closedCause; } // TODO: We could even go further and use a pre-instantiated IOException for the other error codes, but for // all other errors it may be better to just include a stack trace. diff --git a/transport-native-epoll/src/main/java/io/netty/channel/unix/FileDescriptor.java b/transport-native-epoll/src/main/java/io/netty/channel/unix/FileDescriptor.java index 68976c2242..80e21512d5 100644 --- a/transport-native-epoll/src/main/java/io/netty/channel/unix/FileDescriptor.java +++ b/transport-native-epoll/src/main/java/io/netty/channel/unix/FileDescriptor.java @@ -16,15 +16,14 @@ package io.netty.channel.unix; import io.netty.util.internal.PlatformDependent; +import io.netty.util.internal.ThrowableUtil; import java.io.File; import java.io.IOException; import java.nio.ByteBuffer; +import java.nio.channels.ClosedChannelException; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; -import static io.netty.channel.unix.Errors.CONNECTION_RESET_EXCEPTION_READ; -import static io.netty.channel.unix.Errors.CONNECTION_RESET_EXCEPTION_WRITE; -import static io.netty.channel.unix.Errors.CONNECTION_RESET_EXCEPTION_WRITEV; import static io.netty.channel.unix.Errors.ioResult; import static io.netty.channel.unix.Errors.newIOException; import static io.netty.util.internal.ObjectUtil.checkNotNull; @@ -34,6 +33,37 @@ import static io.netty.util.internal.ObjectUtil.checkNotNull; * {@link FileDescriptor} for it. */ public class FileDescriptor { + private static final ClosedChannelException WRITE_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace( + new ClosedChannelException(), FileDescriptor.class, "write(...)"); + private static final ClosedChannelException WRITE_ADDRESS_CLOSED_CHANNEL_EXCEPTION = + ThrowableUtil.unknownStackTrace(new ClosedChannelException(), FileDescriptor.class, "writeAddress(...)"); + private static final ClosedChannelException WRITEV_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace( + new ClosedChannelException(), FileDescriptor.class, "writev(...)"); + private static final ClosedChannelException WRITEV_ADDRESSES_CLOSED_CHANNEL_EXCEPTION = + ThrowableUtil.unknownStackTrace(new ClosedChannelException(), FileDescriptor.class, "writevAddresses(...)"); + private static final ClosedChannelException READ_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace( + new ClosedChannelException(), FileDescriptor.class, "read(...)"); + private static final ClosedChannelException READ_ADDRESS_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace( + new ClosedChannelException(), FileDescriptor.class, "readAddress(...)"); + private static final Errors.NativeIoException WRITE_CONNECTION_RESET_EXCEPTION = ThrowableUtil.unknownStackTrace( + Errors.newConnectionResetException("syscall:write(...)", Errors.ERRNO_EPIPE_NEGATIVE), + FileDescriptor.class, "write(...)"); + private static final Errors.NativeIoException WRITE_ADDRESS_CONNECTION_RESET_EXCEPTION = + ThrowableUtil.unknownStackTrace(Errors.newConnectionResetException("syscall:write(...)", + Errors.ERRNO_EPIPE_NEGATIVE), FileDescriptor.class, "writeAddress(...)"); + private static final Errors.NativeIoException WRITEV_CONNECTION_RESET_EXCEPTION = ThrowableUtil.unknownStackTrace( + Errors.newConnectionResetException("syscall:writev(...)", Errors.ERRNO_EPIPE_NEGATIVE), + FileDescriptor.class, "writev(...)"); + private static final Errors.NativeIoException WRITEV_ADDRESSES_CONNECTION_RESET_EXCEPTION = + ThrowableUtil.unknownStackTrace(Errors.newConnectionResetException("syscall:writev(...)", + Errors.ERRNO_EPIPE_NEGATIVE), FileDescriptor.class, "writeAddresses(...)"); + private static final Errors.NativeIoException READ_CONNECTION_RESET_EXCEPTION = ThrowableUtil.unknownStackTrace( + Errors.newConnectionResetException("syscall:read(...)", Errors.ERRNO_ECONNRESET_NEGATIVE), + FileDescriptor.class, "read(...)"); + private static final Errors.NativeIoException READ_ADDRESS_CONNECTION_RESET_EXCEPTION = + ThrowableUtil.unknownStackTrace(Errors.newConnectionResetException("syscall:read(...)", + Errors.ERRNO_ECONNRESET_NEGATIVE), FileDescriptor.class, "readAddress(...)"); + private static final AtomicIntegerFieldUpdater stateUpdater; static { AtomicIntegerFieldUpdater updater @@ -43,6 +73,7 @@ public class FileDescriptor { } stateUpdater = updater; } + private static final int STATE_CLOSED_MASK = 1; private static final int STATE_INPUT_SHUTDOWN_MASK = 1 << 1; private static final int STATE_OUTPUT_SHUTDOWN_MASK = 1 << 2; @@ -101,7 +132,7 @@ public class FileDescriptor { if (res >= 0) { return res; } - return ioResult("write", res, CONNECTION_RESET_EXCEPTION_WRITE); + return ioResult("write", res, WRITE_CONNECTION_RESET_EXCEPTION, WRITE_CLOSED_CHANNEL_EXCEPTION); } public final int writeAddress(long address, int pos, int limit) throws IOException { @@ -109,7 +140,8 @@ public class FileDescriptor { if (res >= 0) { return res; } - return ioResult("writeAddress", res, CONNECTION_RESET_EXCEPTION_WRITE); + return ioResult("writeAddress", res, + WRITE_ADDRESS_CONNECTION_RESET_EXCEPTION, WRITE_ADDRESS_CLOSED_CHANNEL_EXCEPTION); } public final long writev(ByteBuffer[] buffers, int offset, int length) throws IOException { @@ -117,7 +149,7 @@ public class FileDescriptor { if (res >= 0) { return res; } - return ioResult("writev", (int) res, CONNECTION_RESET_EXCEPTION_WRITEV); + return ioResult("writev", (int) res, WRITEV_CONNECTION_RESET_EXCEPTION, WRITEV_CLOSED_CHANNEL_EXCEPTION); } public final long writevAddresses(long memoryAddress, int length) throws IOException { @@ -125,7 +157,8 @@ public class FileDescriptor { if (res >= 0) { return res; } - return ioResult("writevAddresses", (int) res, CONNECTION_RESET_EXCEPTION_WRITEV); + return ioResult("writevAddresses", (int) res, + WRITEV_ADDRESSES_CONNECTION_RESET_EXCEPTION, WRITEV_ADDRESSES_CLOSED_CHANNEL_EXCEPTION); } public final int read(ByteBuffer buf, int pos, int limit) throws IOException { @@ -136,7 +169,7 @@ public class FileDescriptor { if (res == 0) { return -1; } - return ioResult("read", res, CONNECTION_RESET_EXCEPTION_READ); + return ioResult("read", res, READ_CONNECTION_RESET_EXCEPTION, READ_CLOSED_CHANNEL_EXCEPTION); } public final int readAddress(long address, int pos, int limit) throws IOException { @@ -147,7 +180,8 @@ public class FileDescriptor { if (res == 0) { return -1; } - return ioResult("readAddress", res, CONNECTION_RESET_EXCEPTION_READ); + return ioResult("readAddress", res, + READ_ADDRESS_CONNECTION_RESET_EXCEPTION, READ_ADDRESS_CLOSED_CHANNEL_EXCEPTION); } @Override diff --git a/transport-native-epoll/src/main/java/io/netty/channel/unix/Socket.java b/transport-native-epoll/src/main/java/io/netty/channel/unix/Socket.java index 8e14110291..b54f4f0c90 100644 --- a/transport-native-epoll/src/main/java/io/netty/channel/unix/Socket.java +++ b/transport-native-epoll/src/main/java/io/netty/channel/unix/Socket.java @@ -17,6 +17,7 @@ package io.netty.channel.unix; import io.netty.channel.ChannelException; import io.netty.util.CharsetUtil; +import io.netty.util.internal.ThrowableUtil; import java.io.IOException; import java.net.Inet6Address; @@ -24,10 +25,8 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.ByteBuffer; +import java.nio.channels.ClosedChannelException; -import static io.netty.channel.unix.Errors.CONNECTION_NOT_CONNECTED_SHUTDOWN_EXCEPTION; -import static io.netty.channel.unix.Errors.CONNECTION_RESET_EXCEPTION_SENDMSG; -import static io.netty.channel.unix.Errors.CONNECTION_RESET_EXCEPTION_SENDTO; import static io.netty.channel.unix.Errors.ERRNO_EAGAIN_NEGATIVE; import static io.netty.channel.unix.Errors.ERRNO_EINPROGRESS_NEGATIVE; import static io.netty.channel.unix.Errors.ERRNO_EWOULDBLOCK_NEGATIVE; @@ -42,6 +41,26 @@ import static io.netty.channel.unix.NativeInetAddress.ipv4MappedIpv6Address; * Internal usage only! */ public final class Socket extends FileDescriptor { + private static final ClosedChannelException SHUTDOWN_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace( + new ClosedChannelException(), Socket.class, "shutdown(...)"); + private static final ClosedChannelException SEND_TO_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace( + new ClosedChannelException(), Socket.class, "sendTo(...)"); + private static final ClosedChannelException SEND_TO_ADDRESS_CLOSED_CHANNEL_EXCEPTION = + ThrowableUtil.unknownStackTrace(new ClosedChannelException(), Socket.class, "sendToAddress(...)"); + private static final ClosedChannelException SEND_TO_ADDRESSES_CLOSED_CHANNEL_EXCEPTION = + ThrowableUtil.unknownStackTrace(new ClosedChannelException(), Socket.class, "sendToAddresses(...)"); + private static final Errors.NativeIoException SEND_TO_CONNECTION_RESET_EXCEPTION = ThrowableUtil.unknownStackTrace( + Errors.newConnectionResetException("syscall:sendto(...)", Errors.ERRNO_EPIPE_NEGATIVE), + Socket.class, "sendTo(...)"); + private static final Errors.NativeIoException SEND_TO_ADDRESS_CONNECTION_RESET_EXCEPTION = + ThrowableUtil.unknownStackTrace(Errors.newConnectionResetException("syscall:sendto(...)", + Errors.ERRNO_EPIPE_NEGATIVE), Socket.class, "sendToAddress(...)"); + private static final Errors.NativeIoException CONNECTION_RESET_EXCEPTION_SENDMSG = ThrowableUtil.unknownStackTrace( + Errors.newConnectionResetException("syscall:sendmsg(...)", + Errors.ERRNO_EPIPE_NEGATIVE), Socket.class, "sendToAddresses(...)"); + private static final Errors.NativeIoException CONNECTION_NOT_CONNECTED_SHUTDOWN_EXCEPTION = + ThrowableUtil.unknownStackTrace(Errors.newConnectionResetException("syscall:shutdown(...)", + Errors.ERRNO_ENOTCONN_NEGATIVE), Socket.class, "shutdown(...)"); public Socket(int fd) { super(fd); } @@ -75,7 +94,7 @@ public final class Socket extends FileDescriptor { } int res = shutdown(fd, read, write); if (res < 0) { - ioResult("shutdown", res, CONNECTION_NOT_CONNECTED_SHUTDOWN_EXCEPTION); + ioResult("shutdown", res, CONNECTION_NOT_CONNECTED_SHUTDOWN_EXCEPTION, SHUTDOWN_CLOSED_CHANNEL_EXCEPTION); } } @@ -109,7 +128,7 @@ public final class Socket extends FileDescriptor { if (res >= 0) { return res; } - return ioResult("sendTo", res, CONNECTION_RESET_EXCEPTION_SENDTO); + return ioResult("sendTo", res, SEND_TO_CONNECTION_RESET_EXCEPTION, SEND_TO_CLOSED_CHANNEL_EXCEPTION); } public int sendToAddress(long memoryAddress, int pos, int limit, InetAddress addr, int port) @@ -130,7 +149,8 @@ public final class Socket extends FileDescriptor { if (res >= 0) { return res; } - return ioResult("sendToAddress", res, CONNECTION_RESET_EXCEPTION_SENDTO); + return ioResult("sendToAddress", res, + SEND_TO_ADDRESS_CONNECTION_RESET_EXCEPTION, SEND_TO_ADDRESS_CLOSED_CHANNEL_EXCEPTION); } public int sendToAddresses(long memoryAddress, int length, InetAddress addr, int port) throws IOException { @@ -150,7 +170,8 @@ public final class Socket extends FileDescriptor { if (res >= 0) { return res; } - return ioResult("sendToAddresses", res, CONNECTION_RESET_EXCEPTION_SENDMSG); + return ioResult("sendToAddresses", res, + CONNECTION_RESET_EXCEPTION_SENDMSG, SEND_TO_ADDRESSES_CLOSED_CHANNEL_EXCEPTION); } public DatagramSocketAddress recvFrom(ByteBuffer buf, int pos, int limit) throws IOException { diff --git a/transport/src/main/java/io/netty/channel/AbstractChannel.java b/transport/src/main/java/io/netty/channel/AbstractChannel.java index f1c828952b..ba988d367b 100644 --- a/transport/src/main/java/io/netty/channel/AbstractChannel.java +++ b/transport/src/main/java/io/netty/channel/AbstractChannel.java @@ -18,9 +18,9 @@ package io.netty.channel; import io.netty.buffer.ByteBufAllocator; import io.netty.util.DefaultAttributeMap; import io.netty.util.ReferenceCountUtil; -import io.netty.util.internal.EmptyArrays; 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; @@ -42,13 +42,16 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha private static final InternalLogger logger = InternalLoggerFactory.getInstance(AbstractChannel.class); - static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION = new ClosedChannelException(); - static final NotYetConnectedException NOT_YET_CONNECTED_EXCEPTION = new NotYetConnectedException(); - - static { - CLOSED_CHANNEL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - NOT_YET_CONNECTED_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - } + private static final ClosedChannelException FLUSH0_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace( + new ClosedChannelException(), AbstractUnsafe.class, "flush0()"); + private static final ClosedChannelException ENSURE_OPEN_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace( + new ClosedChannelException(), AbstractUnsafe.class, "ensureOpen(...)"); + private static final ClosedChannelException CLOSE_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace( + new ClosedChannelException(), AbstractUnsafe.class, "close(...)"); + private static final ClosedChannelException WRITE_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace( + new ClosedChannelException(), AbstractUnsafe.class, "write(...)"); + private static final NotYetConnectedException FLUSH0_NOT_YET_CONNECTED_EXCEPTION = ThrowableUtil.unknownStackTrace( + new NotYetConnectedException(), AbstractUnsafe.class, "flush0()"); private final Channel parent; private final long hashCode = ThreadLocalRandom.current().nextLong(); @@ -539,10 +542,11 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha public final void close(final ChannelPromise promise) { assertEventLoop(); - close(promise, CLOSED_CHANNEL_EXCEPTION, false); + close(promise, CLOSE_CLOSED_CHANNEL_EXCEPTION, CLOSE_CLOSED_CHANNEL_EXCEPTION, false); } - private void close(final ChannelPromise promise, final Throwable cause, final boolean notify) { + private void close(final ChannelPromise promise, final Throwable cause, + final ClosedChannelException closeCause, final boolean notify) { if (!promise.setUncancellable()) { return; } @@ -585,7 +589,7 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha public void run() { // Fail all the queued messages outboundBuffer.failFlushed(cause, notify); - outboundBuffer.close(CLOSED_CHANNEL_EXCEPTION); + outboundBuffer.close(closeCause); fireChannelInactiveAndDeregister(wasActive); } }); @@ -599,7 +603,7 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha } finally { // Fail all the queued messages. outboundBuffer.failFlushed(cause, notify); - outboundBuffer.close(CLOSED_CHANNEL_EXCEPTION); + outboundBuffer.close(closeCause); } if (inFlush0) { invokeLater(new Runnable() { @@ -722,7 +726,7 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha // need to fail the future right away. If it is not null the handling of the rest // will be done in flush0() // See https://github.com/netty/netty/issues/2362 - safeSetFailure(promise, CLOSED_CHANNEL_EXCEPTION); + safeSetFailure(promise, WRITE_CLOSED_CHANNEL_EXCEPTION); // release message now to prevent resource-leak ReferenceCountUtil.release(msg); return; @@ -774,10 +778,10 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha if (!isActive()) { try { if (isOpen()) { - outboundBuffer.failFlushed(NOT_YET_CONNECTED_EXCEPTION, true); + outboundBuffer.failFlushed(FLUSH0_NOT_YET_CONNECTED_EXCEPTION, true); } else { // Do not trigger channelWritabilityChanged because the channel is closed already. - outboundBuffer.failFlushed(CLOSED_CHANNEL_EXCEPTION, false); + outboundBuffer.failFlushed(FLUSH0_CLOSED_CHANNEL_EXCEPTION, false); } } finally { inFlush0 = false; @@ -797,7 +801,7 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha * This is needed as otherwise {@link #isActive()} , {@link #isOpen()} and {@link #isWritable()} * may still return {@code true} even if the channel should be closed as result of the exception. */ - close(voidPromise(), t, false); + close(voidPromise(), t, FLUSH0_CLOSED_CHANNEL_EXCEPTION, false); } else { outboundBuffer.failFlushed(t, true); } @@ -813,12 +817,13 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha return unsafeVoidPromise; } + @Deprecated protected final boolean ensureOpen(ChannelPromise promise) { if (isOpen()) { return true; } - safeSetFailure(promise, CLOSED_CHANNEL_EXCEPTION); + safeSetFailure(promise, ENSURE_OPEN_CLOSED_CHANNEL_EXCEPTION); return false; } diff --git a/transport/src/main/java/io/netty/channel/ThreadPerChannelEventLoopGroup.java b/transport/src/main/java/io/netty/channel/ThreadPerChannelEventLoopGroup.java index 4c1cacebc5..62208bf6b3 100644 --- a/transport/src/main/java/io/netty/channel/ThreadPerChannelEventLoopGroup.java +++ b/transport/src/main/java/io/netty/channel/ThreadPerChannelEventLoopGroup.java @@ -26,6 +26,7 @@ import io.netty.util.concurrent.Promise; import io.netty.util.internal.EmptyArrays; import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.ReadOnlyIterator; +import io.netty.util.internal.ThrowableUtil; import java.util.Collections; import java.util.Iterator; @@ -112,8 +113,9 @@ public class ThreadPerChannelEventLoopGroup extends AbstractEventExecutorGroup i this.maxChannels = maxChannels; this.threadFactory = threadFactory; - tooManyChannels = new ChannelException("too many channels (max: " + maxChannels + ')'); - tooManyChannels.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); + tooManyChannels = ThrowableUtil.unknownStackTrace( + new ChannelException("too many channels (max: " + maxChannels + ')'), + ThreadPerChannelEventLoopGroup.class, "nextChild()"); } /** diff --git a/transport/src/main/java/io/netty/channel/local/LocalChannel.java b/transport/src/main/java/io/netty/channel/local/LocalChannel.java index b6df129637..a7f02c0553 100644 --- a/transport/src/main/java/io/netty/channel/local/LocalChannel.java +++ b/transport/src/main/java/io/netty/channel/local/LocalChannel.java @@ -28,9 +28,9 @@ import io.netty.channel.SingleThreadEventLoop; import io.netty.util.ReferenceCountUtil; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.SingleThreadEventExecutor; -import io.netty.util.internal.EmptyArrays; import io.netty.util.internal.InternalThreadLocalMap; import io.netty.util.internal.PlatformDependent; +import io.netty.util.internal.ThrowableUtil; import java.net.ConnectException; import java.net.SocketAddress; @@ -50,7 +50,10 @@ public class LocalChannel extends AbstractChannel { private static final AtomicReferenceFieldUpdater FINISH_READ_FUTURE_UPDATER; private static final ChannelMetadata METADATA = new ChannelMetadata(false); private static final int MAX_READER_STACK_DEPTH = 8; - private static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION = new ClosedChannelException(); + private static final ClosedChannelException DO_WRITE_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace( + new ClosedChannelException(), LocalChannel.class, "doWrite(...)"); + private static final ClosedChannelException DO_CLOSE_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace( + new ClosedChannelException(), LocalChannel.class, "doClose()"); private final ChannelConfig config = new DefaultChannelConfig(this); // To further optimize this we could write our own SPSC queue. @@ -95,7 +98,6 @@ public class LocalChannel extends AbstractChannel { AtomicReferenceFieldUpdater.newUpdater(LocalChannel.class, Future.class, "finishReadFuture"); } FINISH_READ_FUTURE_UPDATER = finishReadFutureUpdater; - CLOSED_CHANNEL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); } public LocalChannel() { @@ -238,7 +240,7 @@ public class LocalChannel extends AbstractChannel { ChannelPromise promise = connectPromise; if (promise != null) { // Use tryFailure() instead of setFailure() to avoid the race against cancel(). - promise.tryFailure(CLOSED_CHANNEL_EXCEPTION); + promise.tryFailure(DO_CLOSE_CLOSED_CHANNEL_EXCEPTION); connectPromise = null; } @@ -332,7 +334,7 @@ public class LocalChannel extends AbstractChannel { throw new NotYetConnectedException(); } if (state > 2) { - throw CLOSED_CHANNEL_EXCEPTION; + throw DO_WRITE_CLOSED_CHANNEL_EXCEPTION; } final LocalChannel peer = this.peer; @@ -351,7 +353,7 @@ public class LocalChannel extends AbstractChannel { peer.inboundBuffer.add(ReferenceCountUtil.retain(msg)); in.remove(); } else { - in.remove(CLOSED_CHANNEL_EXCEPTION); + in.remove(DO_WRITE_CLOSED_CHANNEL_EXCEPTION); } } catch (Throwable cause) { in.remove(cause); diff --git a/transport/src/main/java/io/netty/channel/nio/AbstractNioChannel.java b/transport/src/main/java/io/netty/channel/nio/AbstractNioChannel.java index 11364b67ef..5f6425df6c 100644 --- a/transport/src/main/java/io/netty/channel/nio/AbstractNioChannel.java +++ b/transport/src/main/java/io/netty/channel/nio/AbstractNioChannel.java @@ -29,7 +29,7 @@ import io.netty.channel.ConnectTimeoutException; import io.netty.channel.EventLoop; import io.netty.util.ReferenceCountUtil; import io.netty.util.ReferenceCounted; -import io.netty.util.internal.EmptyArrays; +import io.netty.util.internal.ThrowableUtil; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; @@ -50,11 +50,8 @@ public abstract class AbstractNioChannel extends AbstractChannel { private static final InternalLogger logger = InternalLoggerFactory.getInstance(AbstractNioChannel.class); - private static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION = new ClosedChannelException(); - - static { - CLOSED_CHANNEL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - } + private static final ClosedChannelException DO_CLOSE_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace( + new ClosedChannelException(), AbstractNioChannel.class, "doClose()"); private final SelectableChannel ch; protected final int readInterestOp; @@ -458,7 +455,7 @@ public abstract class AbstractNioChannel extends AbstractChannel { ChannelPromise promise = connectPromise; if (promise != null) { // Use tryFailure() instead of setFailure() to avoid the race against cancel(). - promise.tryFailure(CLOSED_CHANNEL_EXCEPTION); + promise.tryFailure(DO_CLOSE_CLOSED_CHANNEL_EXCEPTION); connectPromise = null; } diff --git a/transport/src/main/java/io/netty/channel/pool/FixedChannelPool.java b/transport/src/main/java/io/netty/channel/pool/FixedChannelPool.java index 6bacb1d27e..a8b249c243 100644 --- a/transport/src/main/java/io/netty/channel/pool/FixedChannelPool.java +++ b/transport/src/main/java/io/netty/channel/pool/FixedChannelPool.java @@ -21,7 +21,7 @@ import io.netty.util.concurrent.EventExecutor; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.FutureListener; import io.netty.util.concurrent.Promise; -import io.netty.util.internal.EmptyArrays; +import io.netty.util.internal.ThrowableUtil; import java.nio.channels.ClosedChannelException; import java.util.ArrayDeque; @@ -35,15 +35,12 @@ import java.util.concurrent.TimeoutException; * number of concurrent connections. */ public final class FixedChannelPool extends SimpleChannelPool { - private static final IllegalStateException FULL_EXCEPTION = - new IllegalStateException("Too many outstanding acquire operations"); - private static final TimeoutException TIMEOUT_EXCEPTION = - new TimeoutException("Acquire operation took longer then configured maximum time"); - - static { - FULL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - TIMEOUT_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - } + private static final IllegalStateException FULL_EXCEPTION = ThrowableUtil.unknownStackTrace( + new IllegalStateException("Too many outstanding acquire operations"), + FixedChannelPool.class, "acquire0(...)"); + private static final TimeoutException TIMEOUT_EXCEPTION = ThrowableUtil.unknownStackTrace( + new TimeoutException("Acquire operation took longer then configured maximum time"), + FixedChannelPool.class, "(...)"); public enum AcquireTimeoutAction { /** diff --git a/transport/src/main/java/io/netty/channel/pool/SimpleChannelPool.java b/transport/src/main/java/io/netty/channel/pool/SimpleChannelPool.java index 62023823db..b61c13f088 100644 --- a/transport/src/main/java/io/netty/channel/pool/SimpleChannelPool.java +++ b/transport/src/main/java/io/netty/channel/pool/SimpleChannelPool.java @@ -25,8 +25,8 @@ import io.netty.util.AttributeKey; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.FutureListener; import io.netty.util.concurrent.Promise; -import io.netty.util.internal.EmptyArrays; import io.netty.util.internal.PlatformDependent; +import io.netty.util.internal.ThrowableUtil; import java.util.Deque; @@ -41,13 +41,12 @@ import static io.netty.util.internal.ObjectUtil.*; */ public class SimpleChannelPool implements ChannelPool { private static final AttributeKey POOL_KEY = AttributeKey.newInstance("channelPool"); - private static final IllegalStateException FULL_EXCEPTION = new IllegalStateException("ChannelPool full"); - private static final IllegalStateException UNHEALTHY_NON_OFFERED_TO_POOL = - new IllegalStateException("Channel is unhealthy not offering it back to pool"); - static { - FULL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - UNHEALTHY_NON_OFFERED_TO_POOL.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - } + private static final IllegalStateException FULL_EXCEPTION = ThrowableUtil.unknownStackTrace( + new IllegalStateException("ChannelPool full"), SimpleChannelPool.class, "releaseAndOffer(...)"); + private static final IllegalStateException UNHEALTHY_NON_OFFERED_TO_POOL = ThrowableUtil.unknownStackTrace( + new IllegalStateException("Channel is unhealthy not offering it back to pool"), + SimpleChannelPool.class, "releaseAndOffer(...)"); + private final Deque deque = PlatformDependent.newConcurrentDeque(); private final ChannelPoolHandler handler; private final ChannelHealthChecker healthCheck;