gpt4 book ai didi

netty - 如果 JVM GC 仍然存在,为什么我们需要手动处理 Netty ByteBuf 的引用计数?

转载 作者:行者123 更新时间:2023-12-03 13:27:54 25 4
gpt4 key购买 nike

照书Netty in Action v10 , reference counting用于处理 ByteBuf 的池化.但是 JVM 不知道 netty 引用计数,所以 JVM 仍然可以 GC ByteBuf .如果是这样,为什么我们还需要关心引用计数并手动调用 release()方法?

我引用了《Netty in Action v10》一书中的一些内容来添加一些上下文。

One of the tradeoffs of reference-counting is that the user have to be carefully when consume messages. While the JVM will still be able to GC such a message (as it is not aware of the reference-counting) this message will not be put back in the pool from which it may be obtained before. Thus chances are good that you will run out of resources at one point if you do not carefully release these messages.



和一些相关的线程:
Buffer ownership in Netty 4: How is buffer life-cycle managed?

https://blog.twitter.com/2013/netty-4-at-twitter-reduced-gc-overhead

加 1

(以下是我的一些理解。)

一个 ByteBuf可以从2个方面进行分类:
1. Pooled or Unpooled
2. Heap-based or Direct

所以可以有4种组合:
(a) Pooled Heap-based
(b) Pooled Direct
(c) Unpooled Heap-based
(d) Unpooled Direct

只有 (a) 和 (c) 受 JVM GC 机制影响,因为它们是基于堆的。

在上述 的引文中,我认为 留言 表示一个 Java 对象,它属于 (a) 类别。

一个终极规则是,如果一个 Java 对象被 GCed,它就完全消失了。所以下面是我认为 Netty 所做的:
  • 对于 (a),Netty 分配器必须 欺骗 JVM GC 使其相信对象永远不应该被 GC .然后使用引用计数将对象移出/移回池中。这是另一种形式的生命周期。
  • 对于 (b),不涉及 JVM GC,因为它不是基于 JVM Heap 的。 Netty 分配器需要使用引用计数将对象移出/移回池中。
  • 对于 (c),JVM GC 完全负责控制对象的生命周期。 Netty 分配器只是提供了分配对象的 API。
  • 对于 (d),不涉及 JVM GC。并且不需要池化。所以 Netty 分配器只需要提供分配/释放对象的 API。
  • 最佳答案

    垃圾收集器间接释放直接缓冲区。我会让你通读这个问题的答案以了解这是如何发生的:Are Java DirectByteBuffer wrappers garbage collected?

    当您执行 I/O 操作时,需要将堆缓冲区复制到直接内存中,然后再由内核处理。当您使用直接缓冲区时,您可以保存复制操作,这是使用直接缓冲区的主要优势。一个缺点是直接内存分配比从 Java 堆分配更昂贵,因此 Netty 引入了池化概念。

    Java 中的池化对象是 polemic topic ,但 Netty 这样做的选择似乎得到了返回,Twitter article你引用的一些证据表明了这一点。对于分配缓冲区的特殊情况,当缓冲区的大小很大时,您可以看到它确实在直接缓冲区和堆缓冲区情况下都带来了好处。

    现在对于池化,GC 在池化时不会回收缓冲区,因为在您使用缓冲区时,您的应用程序有一个或多个对它的引用;或者 Netty 的池有一个对它的引用,当它刚刚被分配并且还没有被提供给你的应用程序或者在你的应用程序使用它并把它还给池之后。

    当您的应用程序在使用缓冲区并且没有进一步引用它之后不调用 release() 时,就会发生泄漏。 ,实际上是什么意思把它放回池中,如果你没有任何进一步的引用。在这种情况下,缓冲区最终将被垃圾收集,但 Netty 的池不会知道它。然后,池会相信您正在使用越来越多的缓冲区,而这些缓冲区永远不会返回到池中。这可能会产生内存泄漏,因为即使缓冲区本身被垃圾收集,用于存储池的内部数据结构也不会。

    关于netty - 如果 JVM GC 仍然存在,为什么我们需要手动处理 Netty ByteBuf 的引用计数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28647048/

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