我在类初始化时遇到了 Netty 的问题。我认为静态字段总是在实例字段之前初始化,但显然情况并非如此:
- AbstractByteBuff 类包含一个
static final ResourceLeakDetector<ByteBuf> leakDetector
- 班级
AbstractReferenceCountedByteBuf extends AbstractByteBuff
- 班级
UnpooledUnsafeDirectByteBuf extends AbstractReferenceCountedByteBuf
第一次创建 UnpooledUnsafeDirectByteBuf 时,会在其构造函数中抛出空指针异常:
protected UnpooledUnsafeDirectByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) {
super(maxCapacity);
if (alloc == null) {
throw new NullPointerException("alloc");
}
if (initialCapacity < 0) {
throw new IllegalArgumentException("initialCapacity: " + initialCapacity);
}
if (maxCapacity < 0) {
throw new IllegalArgumentException("maxCapacity: " + maxCapacity);
}
if (initialCapacity > maxCapacity) {
throw new IllegalArgumentException(String.format(
"initialCapacity(%d) > maxCapacity(%d)", initialCapacity, maxCapacity));
}
this.alloc = alloc;
setByteBuffer(ByteBuffer.allocateDirect(initialCapacity));
leak = leakDetector.open(this);
}
从代码中抛出异常leak = leakDetector.open(this);
。通过使用 intellij Idea 检查,我发现该leakDetector
变量为空。这怎么可能?它是在当前类的超类的超类中初始化的静态变量。
源代码在 Github 上可用,所有引发问题的类都在以下包中可用:https ://github.com/netty/netty/tree/master/buffer/src/main/java/io/netty/缓冲
三个来源如下:
https://github.com/netty/netty/blob/master/buffer/src/main/java/io/netty/buffer/AbstractByteBuf.java
最后一个,AbstractByteBuff,包含泄漏检测器。
请注意,我没有编译源代码,只是链接到 Netty 4.0.7 final。这里是堆栈跟踪:
o.netty.handler.codec.EncoderException: java.lang.NullPointerException
at io.netty.handler.codec.MessageToByteEncoder.write(MessageToByteEncoder.java:131)
at io.netty.channel.DefaultChannelHandlerContext.invokeWrite(DefaultChannelHandlerContext.java:643)
at io.netty.channel.DefaultChannelHandlerContext.write(DefaultChannelHandlerContext.java:633)
at io.netty.handler.codec.MessageToMessageEncoder.write(MessageToMessageEncoder.java:115)
at io.netty.channel.DefaultChannelHandlerContext.invokeWrite(DefaultChannelHandlerContext.java:643)
at io.netty.channel.DefaultChannelHandlerContext.writeAndFlush(DefaultChannelHandlerContext.java:689)
at io.netty.channel.DefaultChannelHandlerContext.writeAndFlush(DefaultChannelHandlerContext.java:713)
at io.netty.channel.DefaultChannelPipeline.writeAndFlush(DefaultChannelPipeline.java:893)
at io.netty.channel.AbstractChannel.writeAndFlush(AbstractChannel.java:239)
at com.logentries.net.NettyBasedAsyncLogger.logLine(NettyBasedAsyncLogger.java:54)
at com.logentries.logback.LogentriesAppender.append(LogentriesAppender.java:105)
at com.logentries.logback.LogentriesAppender.append(LogentriesAppender.java:15)
at ch.qos.logback.core.AppenderBase.doAppend(AppenderBase.java:85)
at ch.qos.logback.core.spi.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:48)
at ch.qos.logback.classic.Logger.appendLoopOnAppenders(Logger.java:280)
at ch.qos.logback.classic.Logger.callAppenders(Logger.java:267)
at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:449)
at ch.qos.logback.classic.Logger.filterAndLog_1(Logger.java:421)
at ch.qos.logback.classic.Logger.debug(Logger.java:514)
at io.netty.util.internal.logging.Slf4JLogger.debug(Slf4JLogger.java:76)
at io.netty.util.ResourceLeakDetector.<clinit>(ResourceLeakDetector.java:37)
at io.netty.buffer.AbstractByteBuf.<clinit>(AbstractByteBuf.java:37)
at io.netty.buffer.UnpooledByteBufAllocator.newDirectBuffer(UnpooledByteBufAllocator.java:49)
at io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:132)
at io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:123)
at io.netty.buffer.AbstractByteBufAllocator.ioBuffer(AbstractByteBufAllocator.java:76)
at io.netty.handler.codec.MessageToByteEncoder.write(MessageToByteEncoder.java:107)
at io.netty.channel.DefaultChannelHandlerContext.invokeWrite(DefaultChannelHandlerContext.java:643)
at io.netty.channel.DefaultChannelHandlerContext.write(DefaultChannelHandlerContext.java:633)
at io.netty.handler.codec.MessageToMessageEncoder.write(MessageToMessageEncoder.java:115)
at io.netty.channel.DefaultChannelHandlerContext.invokeWrite(DefaultChannelHandlerContext.java:643)
at io.netty.channel.DefaultChannelHandlerContext.access$2000(DefaultChannelHandlerContext.java:29)
at io.netty.channel.DefaultChannelHandlerContext$WriteTask.run(DefaultChannelHandlerContext.java:887)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:354)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:366)
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:101)
at java.lang.Thread.run(Thread.java:662)
Caused by: java.lang.NullPointerException
at io.netty.buffer.UnpooledUnsafeDirectByteBuf.<init>(UnpooledUnsafeDirectByteBuf.java:72)
at io.netty.buffer.UnpooledByteBufAllocator.newDirectBuffer(UnpooledByteBufAllocator.java:49)
at io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:132)
at io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:123)
at io.netty.buffer.AbstractByteBufAllocator.ioBuffer(AbstractByteBufAllocator.java:76)
at io.netty.handler.codec.MessageToByteEncoder.write(MessageToByteEncoder.java:107)
... 36 more