Initialization
// org.yeauty.standard.WebsocketServer#init
public void init() throws InterruptedException {<!-- -->
EventLoopGroup boss = new NioEventLoopGroup(config.getBossLoopGroupThreads());
EventLoopGroup worker = new NioEventLoopGroup(config.getWorkerLoopGroupThreads());
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(boss, worker)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, config.getConnectTimeoutMillis())
.option(ChannelOption.SO_BACKLOG, config.getSoBacklog())
.childOption(ChannelOption.WRITE_SPIN_COUNT, config.getWriteSpinCount())
.childOption(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(config.getWriteBufferLowWaterMark(), config.getWriteBufferHighWaterMark()))
.childOption(ChannelOption.TCP_NODELAY, config.isTcpNodelay())
.childOption(ChannelOption.SO_KEEPALIVE, config.isSoKeepalive())
.childOption(ChannelOption.SO_LINGER, config.getSoLinger())
.childOption(ChannelOption.ALLOW_HALF_CLOSURE, config.isAllowHalfClosure())
.handler(new LoggingHandler(LogLevel.DEBUG))
.childHandler(new ChannelInitializer<NioSocketChannel>() {<!-- -->
@Override
protected void initChannel(NioSocketChannel ch) throws Exception {<!-- -->
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new HttpServerCodec()); // Breakpoint. codec
pipeline.addLast(new HttpObjectAggregator(65536));
pipeline.addLast(new HttpServerHandler(pojoEndpointServer, config));
}
});
// io.netty.handler.codec.http.HttpServerCodec#HttpServerCodec(int, int, int)
public HttpServerCodec(int maxInitialLineLength, int maxHeaderSize, int maxChunkSize) {<!-- -->
init(new HttpServerRequestDecoder(maxInitialLineLength, maxHeaderSize, maxChunkSize),
new HttpServerResponseEncoder()); // breakpoint
}
// HttpObjectEncoder
private static final ByteBuf CRLF_BUF = unreleasableBuffer(directBuffer(2).writeByte(CR).writeByte(LF)); // Breakpoint. directBuffer
// io.netty.buffer.Unpooled#directBuffer(int)
public static ByteBuf directBuffer(int initialCapacity) {<!-- -->
// Here ALLOC is a non-pooled UnpooledByteBufAllocator
return ALLOC.directBuffer(initialCapacity);
}
// io.netty.buffer.AbstractByteBufAllocator#directBuffer(int)
@Override
public ByteBuf directBuffer(int initialCapacity) {<!-- -->
return directBuffer(initialCapacity, DEFAULT_MAX_CAPACITY);
}
@Override
public ByteBuf directBuffer(int initialCapacity, int maxCapacity) {<!-- -->
if (initialCapacity == 0 & amp; & amp; maxCapacity == 0) {<!-- -->
return emptyBuf;
}
validate(initialCapacity, maxCapacity);
return newDirectBuffer(initialCapacity, maxCapacity); // breakpoint
}
@Override
protected ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity) {<!-- -->
final ByteBuf buf;
// Breakpoint. Determine whether it is hasUnsafe here (introduced in a separate article), here it is true
// Then judge noCleaner, here is false, go to new InstrumentedUnpooledUnsafeDirectByteBuf
if (PlatformDependent.hasUnsafe()) {<!-- -->
buf = noCleaner ? new InstrumentedUnpooledUnsafeNoCleanerDirectByteBuf(this, initialCapacity, maxCapacity) :
new InstrumentedUnpooledUnsafeDirectByteBuf(this, initialCapacity, maxCapacity);
} else {<!-- -->
buf = new InstrumentedUnpooledDirectByteBuf(this, initialCapacity, maxCapacity);
}
return disableLeakDetector ? buf : toLeakAwareBuffer(buf);
}
// io.netty.buffer.UnpooledByteBufAllocator.InstrumentedUnpooledUnsafeDirectByteBuf#InstrumentedUnpooledUnsafeDirectByteBuf
private static final class InstrumentedUnpooledUnsafeDirectByteBuf extends UnpooledUnsafeDirectByteBuf {<!-- -->
InstrumentedUnpooledUnsafeDirectByteBuf(
UnpooledByteBufAllocator alloc, int initialCapacity, int maxCapacity) {<!-- -->
super(alloc, initialCapacity, maxCapacity);
}
// io.netty.buffer.UnpooledUnsafeDirectByteBuf#UnpooledUnsafeDirectByteBuf(io.netty.buffer.ByteBufAllocator, int, int)
public UnpooledUnsafeDirectByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) {<!-- -->
super(alloc, initialCapacity, maxCapacity);
}
// io.netty.buffer.UnpooledDirectByteBuf#UnpooledDirectByteBuf(io.netty.buffer.ByteBufAllocator, int, int)
public UnpooledDirectByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) {<!-- -->
super(maxCapacity);
ObjectUtil.checkNotNull(alloc, "alloc");
checkPositiveOrZero(initialCapacity, "initialCapacity");
checkPositiveOrZero(maxCapacity, "maxCapacity");
if (initialCapacity > maxCapacity) {<!-- -->
throw new IllegalArgumentException(String.format(
"initialCapacity(%d) > maxCapacity(%d)", initialCapacity, maxCapacity));
}
this.alloc = alloc; // Here is UnpooledByteBufAllocator(directByDefault: true)
setByteBuffer(allocateDirect(initialCapacity), false); // breakpoint allocateDirect
}
// io.netty.buffer.UnpooledByteBufAllocator.InstrumentedUnpooledUnsafeDirectByteBuf#allocateDirect
@Override
protected ByteBuffer allocateDirect(int initialCapacity) {<!-- -->
ByteBuffer buffer = super.allocateDirect(initialCapacity); // Breakpoint
((UnpooledByteBufAllocator) alloc()).incrementDirect(buffer.capacity());
return buffer;
}
// io.netty.buffer.UnpooledDirectByteBuf#allocateDirect
protected ByteBuffer allocateDirect(int initialCapacity) {<!-- -->
return ByteBuffer.allocateDirect(initialCapacity);
}
// java.nio.ByteBuffer#allocateDirect
public static ByteBuffer allocateDirect(int capacity) {<!-- -->
return new DirectByteBuffer(capacity);
}
// java.nio.DirectByteBuffer#DirectByteBuffer(int)
DirectByteBuffer(int cap) {<!-- --> // package-private
super(-1, 0, cap, cap);
boolean pa = VM.isDirectMemoryPageAligned();
int ps = Bits.pageSize();
long size = Math.max(1L, (long)cap + (pa ? ps : 0));
Bits.reserveMemory(size, cap);
long base = 0;
try {<!-- -->
base = UNSAFE.allocateMemory(size); // UNSAFE allocates memory here
} catch (OutOfMemoryError x) {<!-- -->
Bits.unreserveMemory(size, cap);
throw x;
}
UNSAFE.setMemory(base, size, (byte) 0);
// jdk.internal.misc.Unsafe#allocateMemory
public long allocateMemory(long bytes) {<!-- -->
allocateMemoryChecks(bytes);
if (bytes == 0) {<!-- -->
return 0;
}
long p = allocateMemory0(bytes);
if (p == 0) {<!-- -->
throw new OutOfMemoryError();
}
return p;
}
private native long allocateMemory0(long bytes); // native method