private ChannelFuture doStart(ServerPort port) {
            final ServerBootstrap b = new ServerBootstrap();
            serverBootstrap = b;
            config.channelOptions().forEach((k, v) -> {
                @SuppressWarnings("unchecked")
                final ChannelOption<Object> castOption = (ChannelOption<Object>) k;
                b.option(castOption, v);
            });
            config.childChannelOptions().forEach((k, v) -> {
                if (!(port.isDomainSocket() && ChannelUtil.isTcpOption(k))) {
                    @SuppressWarnings("unchecked")
                    final ChannelOption<Object> castOption = (ChannelOption<Object>) k;
                    b.childOption(castOption, v);
                }
            });

            final EventLoopGroup bossGroup = EventLoopGroups.newEventLoopGroup(1, r -> {
                final FastThreadLocalThread thread = new FastThreadLocalThread(r, bossThreadName(port));
                thread.setDaemon(false);
                return thread;
            });

            final GracefulShutdownSupport gracefulShutdownSupport = this.gracefulShutdownSupport;
            assert gracefulShutdownSupport != null;

            ServerPortMetric serverPortMetric = null;
            lock.lock();
            try {
                for (ServerPort serverPort : activePorts.values()) {
                    final InetSocketAddress localAddress = serverPort.localAddress();
                    if (!(localAddress instanceof DomainSocketAddress) &&
                        localAddress.getPort() == port.localAddress().getPort()) {
                        // Because we use the port number for aggregating metrics, use the previous
                        // serverPortMetric.
                        serverPortMetric = serverPort.serverPortMetric();
                        break;
                    }
                }
            } finally {
                lock.unlock();
            }
            if (serverPortMetric == null) {
                serverPortMetric = new ServerPortMetric();
            }
            b.group(bossGroup, config.workerGroup());
            b.handler(connectionLimitingHandler.newChildHandler(serverPortMetric));
            b.childHandler(new HttpServerPipelineConfigurator(config, port, gracefulShutdownSupport,
                                                              hasWebSocketService));
            b.attr(SERVER_PORT_METRIC, serverPortMetric);
            b.childAttr(SERVER_PORT_METRIC, serverPortMetric);

            final SocketAddress localAddress;
            final Class<? extends ServerChannel> channelType;
            final TransportType transportType = Flags.transportType();
            if (port.isDomainSocket()) {
                if (transportType.supportsDomainSockets()) {
                    // Convert to Netty's DomainSocketAddress type.
                    localAddress = ((DomainSocketAddress) port.localAddress()).asNettyAddress();
                    channelType = transportType.domainServerChannelType();
                } else {
                    throw new IllegalStateException(
                            "Unix domains sockets not supported by the current transport type: " +
                            transportType.name());
                }
            } else {
                localAddress = port.localAddress();
                channelType = transportType.serverChannelType();
            }

            b.channel(channelType);
            return b.bind(localAddress);
        }
Registers a JVM shutdown hook that closes this {@link Server} when the current JVM terminates.

@param whenClosing the {@link Runnable} will be run before closing this {@link Server}
core/src/main/java/com/linecorp/armeria/server/Server.java