如果JVM GC仍然存在,为什么需要手动处理Netty ByteBuf的引用计数
根据Netty in Action v10的说法,引用计数用于处理ByteBuf的汇总.但是JVM不知道netty引用计数,所以JVM仍然可以使用ByteBuf.如果是这样,为什么还需要关心引用计数和手动调用release()方法?
我从书中引用了一些,Netty in Action v10>添加一些上下文.
和一些相关的线程: 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机制的影响,因为它们是基于堆的. 在上述的< Netty in Action v10>,我认为该消息是指一个Java对象,它是(a)类别. 一个最终的规则是,如果一个Java对象是GCed,它完全消失了.以下是我认为Netty所做的: >对于(a),Netty分配器必须欺骗JVM GC相信对象不应该被GCed.然后使用引用计数将对象移出/返回到池中.这是生命周期的另一种形式. 解决方法
直接缓冲区被垃圾收集器间接释放.我会让你阅读这个问题的答案,以了解如何发生:
Are Java DirectByteBuffer wrappers garbage collected?
当您执行I / O操作时,堆内存需要被内核处理之前复制到直接内存中.当您使用直接缓冲区时,保存该复制操作,这是使用直接缓冲区的主要优点.缺点是直接内存分配比从java堆分配更为昂贵,因此Netty引入了池化概念. Java中的对象是一个polemic topic,但是Netty的选择似乎有所回报,而您引用的Twitter article显示了一些证据.对于分配缓冲区的具体情况,当缓冲区的大小很大时,您可以看到它在直接和堆缓冲区情况下真正带来好处. 现在要进行池化,GC在汇总时不会回收缓冲区,因为在使用缓冲区时,您的应用程序有一个或多个引用;或Netty的池有一个引用,当它刚刚被分配,还没有被给予你的应用程序,或者你的应用程序使用它,并把它还给池. 当您的应用程序在使用缓冲区并没有进一步引用它之后,会发生泄漏,不会调用release(),实际上意味着将其放回池中,如果您没有进一步的参考.在这种情况下,缓冲区最终将被垃圾回收,但Netty的池不知道.然后池会增长,相信你使用越来越多的缓冲区,这些缓冲区永远不会返回到池中.这可能会产生内存泄漏,因为即使缓冲区本身被垃圾回收,用于存储池的内部数据结构将不会. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |