diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2StreamChannelBootstrap.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2StreamChannelBootstrap.java index 60d7509383..f3007ff7a2 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2StreamChannelBootstrap.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2StreamChannelBootstrap.java @@ -33,6 +33,7 @@ import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; import java.nio.channels.ClosedChannelException; +import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -44,7 +45,9 @@ public final class Http2StreamChannelBootstrap { @SuppressWarnings("unchecked") private static final Map.Entry, Object>[] EMPTY_ATTRIBUTE_ARRAY = new Map.Entry[0]; - private final Map, Object> options = new ConcurrentHashMap, Object>(); + // The order in which ChannelOptions are applied is important they may depend on each other for validation + // purposes. + private final Map, Object> options = new LinkedHashMap, Object>(); private final Map, Object> attrs = new ConcurrentHashMap, Object>(); private final Channel channel; private volatile ChannelHandler handler; @@ -63,10 +66,13 @@ public final class Http2StreamChannelBootstrap { @SuppressWarnings("unchecked") public Http2StreamChannelBootstrap option(ChannelOption option, T value) { ObjectUtil.checkNotNull(option, "option"); - if (value == null) { - options.remove(option); - } else { - options.put(option, value); + + synchronized (options) { + if (value == null) { + options.remove(option); + } else { + options.put(option, value); + } } return this; } @@ -202,7 +208,12 @@ public final class Http2StreamChannelBootstrap { if (handler != null) { p.addLast(handler); } - setChannelOptions(channel, options.entrySet().toArray(EMPTY_OPTION_ARRAY)); + final Map.Entry, Object> [] optionArray; + synchronized (options) { + optionArray = options.entrySet().toArray(EMPTY_OPTION_ARRAY); + } + + setChannelOptions(channel, optionArray); setAttributes(channel, attrs.entrySet().toArray(EMPTY_ATTRIBUTE_ARRAY)); }