@@ -241,13 +241,6 @@ public Runnable start(Listener transportListener) {
241241 b .channelFactory (channelFactory );
242242 // For non-socket based channel, the option will be ignored.
243243 b .option (SO_KEEPALIVE , true );
244- // For non-epoll based channel, the option will be ignored.
245- if (keepAliveTimeNanos != KEEPALIVE_TIME_NANOS_DISABLED ) {
246- ChannelOption <Integer > tcpUserTimeout = Utils .maybeGetTcpUserTimeoutOption ();
247- if (tcpUserTimeout != null ) {
248- b .option (tcpUserTimeout , (int ) TimeUnit .NANOSECONDS .toMillis (keepAliveTimeoutNanos ));
249- }
250- }
251244 for (Map .Entry <ChannelOption <?>, ?> entry : channelOptions .entrySet ()) {
252245 // Every entry in the map is obtained from
253246 // NettyChannelBuilder#withOption(ChannelOption<T> option, T value)
@@ -286,6 +279,20 @@ public void run() {
286279 };
287280 }
288281 channel = regFuture .channel ();
282+ // For non-epoll based channel, the option will be ignored.
283+ try {
284+ if (keepAliveTimeNanos != KEEPALIVE_TIME_NANOS_DISABLED
285+ && Class .forName ("io.netty.channel.epoll.AbstractEpollChannel" ).isInstance (channel )) {
286+ ChannelOption <Integer > tcpUserTimeout = Utils .maybeGetTcpUserTimeoutOption ();
287+ if (tcpUserTimeout != null ) {
288+ int tcpUserTimeoutMs = (int ) TimeUnit .NANOSECONDS .toMillis (keepAliveTimeoutNanos );
289+ channel .config ().setOption (tcpUserTimeout , tcpUserTimeoutMs );
290+ }
291+ }
292+ } catch (ClassNotFoundException ignored ) {
293+ // JVM did not load AbstractEpollChannel, so the current channel will not be of epoll type,
294+ // so there is no need to set TCP_USER_TIMEOUT
295+ }
289296 // Start the write queue as soon as the channel is constructed
290297 handler .startWriteQueue (channel );
291298 // This write will have no effect, yet it will only complete once the negotiationHandler
0 commit comments