iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >一文学习Java NIO的ByteBuffer工作原理
  • 135
分享到

一文学习Java NIO的ByteBuffer工作原理

2024-04-02 19:04:59 135人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

目录1 api2 Netty 的数据容器2.1 工作原理内存池化非池化的堆内与堆外的 ByteBuf池化的堆内与堆外的 ByteBuf字节级操作派生缓冲区slice、slice(in

网络数据的基本单位永远是 byte(字节)。Java NIO 提供 ByteBuffer 作为字节的容器,但该类过于复杂,有点难用。

ByteBuf是Netty当中的最重要的工具类,它与jdk的ByteBuffer原理基本上相同,也分为堆内与堆外俩种类型,但是ByteBuf做了极大的优化,具有更简单的API,更多的工具方法和优秀的内存池设计。

1 API

Netty 的数据处理 API 通过两个组件暴露——抽象类ByteBuf 和 接口 ByteBufHolder。

ByteBuf API 的优点:

  • 它可以被用户自定义的缓冲区类型扩展
  • 通过内置的复合缓冲区类型实现了透明的零拷贝;
  • 容量可以按需增长(类似于 JDK 的 StringBuilder)
  • 在读和写这两种模式之间切换不需要调用 ByteBuffer 的 flip()方法
  • 读和写使用了不同的索引
  • 支持方法的链式调用
  • 支持引用计数
  • 支持池化

其他类可用于管理 ByteBuf 实例的分配,以及执行各种针对于数据容器本身和它所持有的数据的操作。

2 Netty 的数据容器

所有网络通信最终都是基于底层的字节流传输,因此高效、方便、易用的数据接口是迷人的,而 Netty 的 ByteBuf 生而为满足这些需求。

2.1 工作原理

ByteBuf 维护俩不同索引:一个用于读取,一个用于写入:

  • 从 ByteBuf 读取时,其 readerIndex 将会被递增已经被读取的字节数
  • 当写入 ByteBuf 时,writerIndex 也会被递增
  • 一个读索引和写索引都设置为 0 的 16 字节 ByteBuf


这些索引两两之间有什么关系呢?
若打算读取字节直到 readerIndex == writerIndex,会发生啥?此时,将会到达“可读取的”数据的末尾。类似试图读取超出数组末尾的数据一样,试图读取超出该点的数据也会抛 IndexOutOfBoundsException

  • read、write 开头的 ByteBuf 方法,会推进对应索引
  • set、get 开头的操作则不会。后面的这些方法将在作为一个参数传入的一个相对索引上执行操作

可指定 ByteBuf 的最大容量。试图移动写索引(即 writerIndex)超过这个值将会触
发一个异常。(默认限制 Integer.MAX_VALUE。)

内存池化

非池化的堆内与堆外的 ByteBuf

示意图


ByteBuf heapBuffer = UnpooledByteBufAllocator.DEFAULT.heapBuffer(10);
ByteBuf directBuffer = UnpooledByteBufAllocator.DEFAULT.directBuffer(10);

注意要手动将GC 无法控制的非堆内存的空间释放:

池化的堆内与堆外的 ByteBuf

示意图

字节级操作

派生缓冲区

派生缓冲区为 ByteBuf 提供了以专门的方式来呈现其内容的视图。这类视图通过以下方法创建:

  • Unpooled.unmodifiableBuffer(…)
  • order(ByteOrder)
  • readSlice(int)

这些方法都将返回一个新的 ByteBuf 实例,但都具有自己独立的读、写和标记索引。
其内部存储和 JDK 的 ByteBuffer 一样,都是共享的。所以派生缓冲区的创建成本很低,但同时也表明若你修改了它的内容,也会同时修改对应源实例!

slice、slice(int, int)、retainedSlice、retainedSlice(int, int)

返回此缓冲区的可读字节的一部分
此方法与buf.slice(buf.readerIndex(), buf.readableBytes())相同。
该方法不会调用retain(),引用计数不会增加。
retainedSlice系列方法调用类似slice().retain(),但此方法可能返回产生较少垃圾的缓冲区实现。

duplicate、retainedDuplicate

返回一个共享该缓冲区整个区域的缓冲区。
此方法不会修改此缓冲区的readerIndex或writerIndex

读取器和写入器标记将不会重复。
duplicate不会调用retain(),不会增加引用计数,而retainedDuplicate会。

readSlice、readRetainedSlice

返回部分空间,彼此共享底层缓冲区,会增加原缓冲区的readerIndex。

如果需要一个现有缓冲区的真实副本,请使用 copy()或者 copy(int, int),因为这个调用所返回的 ByteBuf 拥有独立的数据副本。

引用与释放

ByteBuf 在使用完毕后一定要记得释放,否则会造成内存泄露。

引用计数

通过在某个对象所持有的资源不再被其他对象引用时释放该对象所持有的资源来优化内存使用和性能的技术。
Netty 在4.x为 ByteBuf 和 ByteBufHolder 带来了引用计数技术,都实现了:

ReferenceCounted接口

需要显式释放的引用计数对象。

当一个新的ReferenceCounted被实例化时,以1 作为初始值。

retain()

增加引用计数,将引用计数加1。只要引用计数>0,就能保证对象不会被释放。

release()

减少引用计数,将引用计数减1。若引用计数减少到0 ,对象将被显式释放,并且访问释放的对象通常会导致访问冲突。

若实现ReferenceCounted的对象是其他实现ReferenceCounted的对象的容器,则当容器的引用计数变为 0 时,所包含的对象也将通过release()被释放。

引用计数对于池化实现(如 PooledByteBufAllocator)很重要,它降低了内存分配的开销。


Channel channel = ...;
// 从 Channel 获取 ByteBufAllocator
ByteBufAllocator allocator = channel.alloc();
...
// 从 ByteBufAllocator 分配一个 ByteBuf
ByteBuf buffer = allocator.directBuffer();
// 检查引用计数是否为预期的 1
assert buffer.refCnt() == 1;


ByteBuf buffer = ...;
// 减少该对象的活动引用。当减少到 0 时,该对象被释放,该方法返回 true
boolean released = buffer.release();

试图访问一个已经被释放的引用计数的对象,将会抛IllegalReferenceCountException

一个特定的(ReferenceCounted 的实现)类,可以用它自己的独特方式来定义它的引用计数规则。例如可以设想一个类,其 release()方法的实现总是将引用计数设为
零,而不用关心它的当前值,从而一次性使所有的活动引用都失效。

谁负责释放

一般由最后访问(引用计数)对象的那一方来负责将它释放。

以上就是一文学习Java NIO的ByteBuffer工作原理的详细内容,更多关于Java NIO的ByteBuffer的资料请关注编程网其它相关文章!

--结束END--

本文标题: 一文学习Java NIO的ByteBuffer工作原理

本文链接: https://www.lsjlt.com/news/127236.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 一文学习Java NIO的ByteBuffer工作原理
    目录1 API2 Netty 的数据容器2.1 工作原理内存池化非池化的堆内与堆外的 ByteBuf池化的堆内与堆外的 ByteBuf字节级操作派生缓冲区slice、slice(in...
    99+
    2024-04-02
  • Java NIO的ByteBuffer工作原理是什么
    这篇文章给大家介绍Java NIO的ByteBuffer工作原理是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。1 APINetty 的数据处理 API 通过两个组件暴露——抽象类ByteBuf 和 接口 Byte...
    99+
    2023-06-15
  • Java NIO的的介绍及工作原理是什么
    这篇文章主要讲解了“Java NIO的的介绍及工作原理是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java NIO的的介绍及工作原理是什么”吧!针对传统I/O 工作模式的不足,NIO...
    99+
    2023-06-17
  • 一篇文章带你学习JAVA MyBatis底层原理
    目录一、传统JDBC的弊端二、mybatis介绍三、MyBatis架构图核心类解释工作流程四、自己通过加载xml配置走mybais流程实现例子总结一、传统JDBC的弊端 j...
    99+
    2024-04-02
  • 一文理解Redux及其工作原理
    目录一、是什么二、工作原理三、如何使用小结一、是什么 React是用于构建用户界面的,帮助我们解决渲染DOM的过程 而在整个应用中会存在很多个组件,每个组件的state是由自身进行管...
    99+
    2024-04-02
  • Java EE 期末复习提纲【太原理工大学】
    目录 一、题型 二、考点 1. MyBatis 2. Spring 3. Spring MVC 一、题型 选择题 20 个,每个 1 分,共 20 分。 填空题 20 个,每个 1 分,共 20 分。 判断题 10 个,每个 1...
    99+
    2023-09-06
    java-ee java
  • HashSet工作原理_动力节点Java学院整理
    对于 HashSet 而言,它是基于 HashMap 实现的,HashSet 底层采用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,查看 HashSet 的源代码,可以看到如下代码:public class Has...
    99+
    2023-05-31
    java hashset hs
  • Node学习之聊聊Cookie-Session登录验证的工作原理
    为什么不单独使用Cookie?Cookie是存放在浏览器中的,可以在浏览器中打开控制台,选择应用,找到存储中的Cookie进行查看:当客户端向服务端发送网络请求时浏览器会自动将Cookie添加到请求头中,这样服务端就能获取这个Cookie,...
    99+
    2023-05-14
    Node.js node
  • Spring mvc工作原理_动力节点Java学院整理
    SpringMVC框架介绍Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。使用 Sprin...
    99+
    2023-05-31
    spring mvc 工作原理
  • java线程池的工作原理
    这篇文章主要讲解了“java线程池的工作原理”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“java线程池的工作原理”吧!一、线程池创建先看一下ThreadPoolExecutor参数最全的构...
    99+
    2023-05-30
  • 在java中session的工作原理
    java中session的工作原理:在创建Session对象时,会有一个SESSION ID,它是唯一的、不重复的、不容易找到规律的字符串。在创建Session对象时,同时创建一个特殊的Cookie对象,并且会将这个特殊的Cookie对象携...
    99+
    2024-04-02
  • Java GC的工作原理介绍
    本篇内容主要讲解“Java GC的工作原理介绍”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java GC的工作原理介绍”吧!JVM内存结构由堆、栈、本地方法栈、方法区等部分组成,结构图如下所示...
    99+
    2023-06-17
  • 一文带你学习Java中的线程
    目录介绍线程通用的线程生命周期Java 的线程生命周期Java 的线程状态切换从 NEW 到 RUNNABLE 状态从 RUNNABLE 到 TERMINATED 状态1. RUNN...
    99+
    2023-05-20
    Java 线程 Java线程总结
  • java servlet的工作原理是什么
    Java Servlet是一种用于在服务器上处理客户端请求的Java程序。它的工作原理如下:1. 客户端发送HTTP请求到服务器。这...
    99+
    2023-09-25
    java servlet
  • Java学习之缓冲流的原理详解
    目录前言字节缓冲流原理字符缓冲流前言 前面我们已经学习了四种对文件数据操作的基本流,字节输入流,字节输出流,字符输入流,字符输出流。为了提高其数据的读写效率,Java中又定义了四种缓...
    99+
    2023-01-28
    Java缓冲流原理 Java缓冲流
  • java session的工作原理是什么
    Java中的Session是一种用于在服务器端存储用户数据的机制。它的工作原理如下:1. 当用户第一次访问服务器时,服务器会为该用户...
    99+
    2023-09-20
    java
  • Windows操作系统的DLL文件工作原理
    什么是.dll文件? .dll文件指的是动态链接库(Dynamic Link Library)文件。这些文件包含可被程序在运行时调用的代码和数据。它们是Windows操作系统中重要的组成部分,允许程序共享资源,提高效率并...
    99+
    2023-11-21
    Windows DLL 文件
  • java jbpm工作流的原理是什么
    jBPM(Java Business Process Management)是一个基于Java的开源工作流引擎,它用于执行和管理业务...
    99+
    2023-09-09
    java
  • Java工作流Activity的原理是什么
    Java工作流Activity的原理是基于活动(Activity)的概念。活动是业务中的具体操作或步骤,可以是一个服务、一个任务或者...
    99+
    2023-10-19
    Java
  • servlet之session工作原理简介_动力节点Java学院整理
    要了解Session的底层工作原理。我们还是先看在一个会话过程中,同一个浏览器在访问多个web资源的情况好了,大致分为以下几个步骤:1,浏览器访问某个Servlet,这时如果服务器要从请求对象中获取Session对象(第一次获取也是创建),...
    99+
    2023-05-31
    servlet session
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作