开篇

Netty的ByteBuf有从不同角度有如下2个分类,4种组合!

堆外内存和堆内内存

池化和非池化

我们在利用Netty做底层通信框架的时候,会默认给我们的到底是哪一种组合了?

分析

池化分析

Netty的Boostrap启动类按照标准模板,通常会添加这个配置option(ChannelOption.ALLOCATOR, ByteBufAllocator.DEFAULT)

val serverBootstrap = ServerBootstrap().group(bossGroup, workGroup)

.channel(NioServerSocketChannel::class.java) //配置客户端的channel类型 .option(ChannelOption.ALLOCATOR, ByteBufAllocator.DEFAULT)

//.....

那么通过默认的ByteBufAllocator.DEFAULT分配出来的是哪一种组合了?我们来通过代码分析。

首先看看这个ByteBufAllocator.DEFAULT创建了一个什么类

public interface ByteBufAllocator {

ByteBufAllocator DEFAULT = ByteBufUtil.DEFAULT_ALLOCATOR;

}

继续调用下去,下述代码省略了一些无关的细节!

public final class ByteBufUtil {

static final ByteBufAllocator DEFAULT_ALLOCATOR;

static {

//核心语句 String allocType = SystemPropertyUtil.get(

"io.netty.allocator.type", PlatformDependent.isAndroid() ? "unpooled" : "pooled");

allocType = allocType.toLowerCase(Locale.US).trim();

ByteBufAllocator alloc;

if ("unpooled".equals(allocType)) {

alloc = UnpooledByteBufAllocator.DEFAULT;

} else if ("pooled".equals(allocType)) {

alloc = PooledByteBufAllocator.DEFAULT;

} else {

alloc = PooledByteBufAllocator.DEFAULT;

}

//这里赋值了噢... DEFAULT_ALLOCATOR = alloc;

}

上述代码最为核心的一句是:

String allocType = SystemPropertyUtil.get(

"io.netty.allocator.type", PlatformDependent.isAndroid() ? "unpooled" : "pooled")

其表达的意思是

从系统配置(通常是启动的命令行给的)中读取io.netty.allocator.type,如果能够读取到,那么按照配置设置。但是这个参数我们通常是没有设置的,所以会进行第二步判定

当读取不到的情况下,又进行了一个判定:PlatformDependent.isAndroid(),当Netty运行在Android的时候是unpooled,否则是pooled

后面的代码就是根据pooled和unpooled来进行对象初始化了。

综上,我们大多数时候启动参数都是没有加对应配置的,且运行在非安卓的系统,所以是pooled的ByteBuf

堆外/堆外

接下来还需要确定默认情况下分配的ByteBuf是分配到堆内还是堆外的,从PooledByteBufAllocator.DEFAULT;点进去可以看到这个代码

public static final PooledByteBufAllocator DEFAULT =

new PooledByteBufAllocator(PlatformDependent.directBufferPreferred());

这个构造函数的参数directBufferPreferred的中文意思不就是偏向堆外内存吗?不过按照传统这个应该是一个boolean的变量,猜测了这些,我们继续看经过省略的源码PlatformDependent。

public final class PlatformDependent {

private static final boolean DIRECT_BUFFER_PREFERRED;

static {

if (!isAndroid()) {

if (javaVersion() >= 9) {

CLEANER = CleanerJava9.isSupported() ? new CleanerJava9() : NOOP;

} else {

CLEANER = CleanerJava6.isSupported() ? new CleanerJava6() : NOOP;

}

} else {

CLEANER = NOOP;

}

DIRECT_BUFFER_PREFERRED = CLEANER != NOOP && !SystemPropertyUtil.getBoolean("io.netty.noPreferDirect", false);

}

核心的参数DIRECT_BUFFER_PREFERRED要想为true必须经过2步:

通过判定获取CLEANER,这个判定牵扯到了另外的判定,这里就不贴代码了,意思应该就是有没有堆外内存的清理办法,Java7+应该都有的

然后判定系统参数io.netty.noPreferDirect是不是为false

通常Java后端的系统这2个条件都是满足的,所以恭喜:DIRECT_BUFFER_PREFERRED为true,堆外内存。

优劣

通过上面分析,我们知道了Netty默认的ByteBuf是堆外的池化模式,那么池化与否和堆外与否各自的优劣在哪里!?

通常池化意味者可以复用资源,减少系统资源的开销

堆外内存可以使用更多可用的空间,毕竟Java虚拟机的大小一般都要小于系统的大小。但是江湖传言堆外内存的开辟比堆内内存的开辟慢,这一点我不太能理解,这里记录下。

以下是我在发文后的第二天从java.nio.ByteBuffer看到的文档注释!

A direct byte buffer may be created by invoking the {@link #allocateDirect(int) allocateDirect} factory method of this class. The buffers returned by this method typically have somewhat higher allocation and deallocation costs than non-direct buffers.

上文的意思翻译下就是

堆外内存的创建可以通过调用allocateDirect这个工厂方法来创建。通过这个方法创建的buffer通常来说会比非堆外内存有更高的创建和释放成本。

这里我还是纳闷啊!**不是说C的效率要高于Java吗?为什么堆外内存的创建和释放会比堆内内存的成本更高了?**有知道的大佬吗?

结语

本篇文章主要通过启动参数的配置,进行了源码分析,确认了Netty的ByteBuf使用的是堆外的池外模式。

骐骥一跃,不能十步。驽马十驾,功在不舍。

bytebuf池_Netty默认的Bytebuf是堆内还是堆外?池化or非池化?相关推荐

  1. java 查看堆外内存占用_如何监控和诊断JVM堆内和堆外内存使用?

    上一讲我介绍了 JVM 内存区域的划分,总结了相关的一些概念,今天我将结合 JVM 参数.工具等方面,进一步分析 JVM 内存结构,包括外部资料相对较少的堆外部分. 今天我要问你的问题是,如何监控和诊 ...

  2. java堆内与堆外数据交互_Java:汇总堆外数据

    java堆内与堆外数据交互 探索如何以最小的垃圾回收影响和最大的内存利用率创建堆​​外聚合. 使用Java Map,List和Object创建大型聚合通常会产生大量堆内存开销. 这也意味着,一旦聚合超 ...

  3. Spark 内存管理堆内和堆外内存规划_大数据培训

    堆内和堆外内存规划 作为一个 JVM 进程,Executor 的内存管理建立在 JVM 的内存管理之上,Spark 对 JVM 的堆内(On-heap)空间进行了更为详细的分配,以充分利用内存.同时, ...

  4. bytebuf池_netty中的ByteBuf

    网络数据的基本单位总是字节.Java NIO 提供了 ByteBuffer 作为它 的字节容器,但是这个类使用起来过于复杂,而且也有些繁琐. Netty 的 ByteBuffer 替代品是 ByteB ...

  5. bytebuf池_Netty篇:ByteBuf之内存池源码分析

    Netty的内存池的实现有些复杂,使用了大量的位运算,晦涩难懂,不过万能的博客上好多大神已经介绍的非常详细,推荐四篇很详细很棒的源码分析的文章链接,本文根据自己的理解顺一下思路,内容主要也是出自以下四 ...

  6. bytebuf池_Netty java从ByteBuf获取数据

    ByteBuf buf = ... byte[] bytes = new byte[buf.readableBytes()]; buf.readBytes(bytes); 如果您不希望readerIn ...

  7. 使用堆内内存HeapByteBuffer的注意事项

    分享一个很多人容易踩的一个坑:HeapByteBuffer 的使用问题.我们都知道 NIO 分装了 ByteBuffer 接口,使得 filechannel 的文件 IO API 变得非常的简单.By ...

  8. spark从入门到精通spark内存管理详解- 堆内堆外内存管理

    前言 Spark作为一个基于内存的分布式计算引擎,其内存管理模块在整个系统中扮演着非常重要的角色.理解Spark内存管理的基本原理,有助于更好地开发Spark应用程序和进行性能调优.本文将详细介绍两部 ...

  9. Netty 的 ByteBuf 是如何支持 堆内存非池化 实现的

    Netty的ByteBuf是如何支持堆内存非池化实现的 ByteBuffer 从实现方式上分成 HeapByteBuffer 和 DirectByteBuffer 两种内存实现方式, HeapByte ...

最新文章

  1. js更改html元素颜色,HTML - 使用JS根据值更改文本的颜色
  2. 文件系统与数据库的优缺点
  3. 结果集(ResultSet)用法
  4. 三甲医院需要部署哪些网络安全设备
  5. Node.js环境搭建npm安装
  6. 【原创】cocos2d-x3.9蓝牙开发之蓝牙开启
  7. 将COleDateTime类型数据转换成char *数据
  8. showModalDialog和showModelessDialog使用心得*转*
  9. svr测试用MATLAB,基于MATLAB的SVR回归模型的设计方案.doc
  10. java编程入门到精通课后答案,附源代码
  11. Python 好友管理系统【简单易懂,代码可以直接运行】
  12. elasticsearch-carrot2插件打包
  13. 2021 个人成长复盘
  14. dbm与mysql_关于dBm与功率转换
  15. STM32 Flash读写;Flash地址对应的存储内容及方式;
  16. Python之网络编程
  17. 「PyTorch自然语言处理系列」7. 自然语言处理的进阶序列模型
  18. Redis Cluster节点添加/删除实录
  19. Java中的Filter
  20. JavaScript代码在哪里放置?

热门文章

  1. c语言复制的代码不能运行,刚学C语言,在Linux下写的代码能正常编译,复制到VC下就无法运行...
  2. php ip访问mysql什么配置_PHP与MYSQL配合完成IP的存取
  3. 【Android】SDDL刷机
  4. Spark学习之概念了解
  5. 列表生成式、生成器、迭代器
  6. 禁用viewstate怎么还保存状态?
  7. CalendarExtender控件的中文显示问题
  8. Installshield在安装结束时刷新系统
  9. 新一轮的心情整理(有二年没来这里了)
  10. ABP 拦截器不工作