gpt4 book ai didi

java - Java : exception with Netty 4. 0.7 中的初始化顺序

转载 作者:行者123 更新时间:2023-12-04 04:45:09 31 4
gpt4 key购买 nike

我在类初始化时遇到了 Netty 的问题。我认为静态字段总是在实例字段之前初始化,但显然情况并非如此:

  • AbstractByteBuff 类包含一个 static final ResourceLeakDetector<ByteBuf> leakDetector
  • 类(class)AbstractReferenceCountedByteBuf extends AbstractByteBuff
  • 类(class)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变量为空。这怎么可能?它是在当前类的父类(super class)的父类(super class)中初始化的静态变量。

    源代码可以在 Github 上找到,所有引发问题的类都可以在以下包中找到: https://github.com/netty/netty/tree/master/buffer/src/main/java/io/netty/buffer

    三个来源如下:

    https://github.com/netty/netty/blob/master/buffer/src/main/java/io/netty/buffer/UnpooledUnsafeDirectByteBuf.java

    https://github.com/netty/netty/blob/master/buffer/src/main/java/io/netty/buffer/AbstractReferenceCountedByteBuf.java

    https://github.com/netty/netty/blob/master/buffer/src/main/java/io/netty/buffer/AbstractByteBuf.java

    最后一个 AbstractByteBuff 包含leakDetector。

    请注意,我不是在编译源代码,而是链接到 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

    最佳答案

    堆栈跟踪表明您的问题:

    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)
    "<clinit>"意味着这些类正在它们的类初始化中。看起来 ResourceLeakDetector 在类初始化期间生成了一条日志语句(在 AbstractByteBuf 的类初始化完成并分配了leakDetector 之前)。

    更新:

    查看整个堆栈跟踪最令人困惑的部分可能是尚未发生的事情尚不清楚。关键是 UnpooledUnsafeDirectByteBuf的静态类初始化还没有发生! jvm的当前状态是:
  • UnpooledByteBufAllocator 正在尝试创建 UnpooledUnsafeDirectByteBuf 的新实例
  • UnpooledUnsafeDirectByteBuf 类已加载(但未初始化)
  • AbstractReferenceCountedByteBuf 类已加载(但未初始化),因为它是 UnpooledUnsafeDirectByteBuf
  • 的父类
  • AbstractByteBuf 类已加载(但未初始化),因为它是 AbstractReferenceCountedByteBuf
  • 的父类
  • AbstractByteBuf 类初始化开始(因为 parent 先于 child ),leakDetector 仍然为空
  • ResourceLeakDetector 类被加载,因为它被 AbstractByteBuf 类初始化
  • 引用
  • ResourceLeakDetector 类初始化开始,其中包含一条日志语句
  • ...进行了大量其他方法调用...
  • UnpooledByteBufAllocator 创建一个 UnpooledUnsafeDirectByteBuf 的新实例(这是对该方法的递归调用)
  • 分配了 UnpooledUnsafeDirectByteBuf 的新实例(该类已经加载,但尚未初始化)
  • 空指针异常

  • 如果您从 ResourceLeakDetector 类 init 中删除了日志记录调用,则会发生以下情况:
  • ResourceLeakDetector 类初始化运行完成
  • AbstractByteBuf 类初始化完成,leakDetector 现在被分配
  • AbstractReferenceCountedByteBuf 类初始化运行完成
  • UnpooledUnsafeDirectByteBuf 类初始化运行完成
  • UnpooledByteBufAllocator 创建一个 UnpooledUnsafeDirectByteBuf 的新实例
  • 生活幸福快乐
  • 关于java - Java : exception with Netty 4. 0.7 中的初始化顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18314986/

    31 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com