@Override
    public final void initialize(ChannelHandlerContext ctx) {
        // Avoid the case where destroy() is called before scheduling timeouts.
        // See: https://github.com/netty/netty/issues/143
        if (isInitialized) {
            return;
        }
        isInitialized = true;

        final long connectionStartTimeNanos = System.nanoTime();
        ctx.channel().closeFuture().addListener(unused -> {
            keepAliveTimer.record(System.nanoTime() - connectionStartTimeNanos, TimeUnit.NANOSECONDS);
            destroy();
        });

        lastConnectionIdleTime = lastPingIdleTime = connectionStartTimeNanos;
        if (connectionIdleTimeNanos > 0) {
            connectionIdleTimeout = executor().schedule(new ConnectionIdleTimeoutTask(ctx),
                                                        connectionIdleTimeNanos, TimeUnit.NANOSECONDS);
        }
        if (pingIdleTimeNanos > 0) {
            pingIdleTimeout = executor().schedule(new PingIdleTimeoutTask(ctx),
                                                  pingIdleTimeNanos, TimeUnit.NANOSECONDS);
        }
        if (maxConnectionAgeNanos > 0) {
            maxConnectionAgeFuture = executor().schedule(new MaxConnectionAgeExceededTask(ctx),
                                                         maxConnectionAgeNanos, TimeUnit.NANOSECONDS);
        }
    }
An {@link AbstractKeepAliveHandler} that writes a PING when neither read nor write was performed for
the specified {@code pingIntervalMillis}, and closes the connection
when neither read nor write was performed within the given {@code idleTimeoutMillis}.
core/src/main/java/com/linecorp/armeria/internal/common/AbstractKeepAliveHandler.java