JDK又在写Bug!告诉你为何Java NIO的ByteBuffer这么垃圾!(下)

简介: JDK又在写Bug!告诉你为何Java NIO的ByteBuffer这么垃圾!

readSlice、readRetainedSlice

image.png



返回部分空间,彼此共享底层缓冲区,会增加原缓冲区的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

image.png



一个特定的(ReferenceCounted 的实现)类,可以用它自己的独特方式来定义它的引用计数规则。例如可以设想一个类,其 release()方法的实现总是将引用计数设为

零,而不用关心它的当前值,从而一次性使所有的活动引用都失效。



谁负责释放

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

目录
相关文章
|
安全 Oracle Java
JAVA高级开发必备·卓伊凡详细JDK、JRE、JVM与Java生态深度解析-形象比喻系统理解-优雅草卓伊凡
JAVA高级开发必备·卓伊凡详细JDK、JRE、JVM与Java生态深度解析-形象比喻系统理解-优雅草卓伊凡
804 0
JAVA高级开发必备·卓伊凡详细JDK、JRE、JVM与Java生态深度解析-形象比喻系统理解-优雅草卓伊凡
|
Oracle Java 关系型数据库
新手必看:Java 开发环境搭建之 JDK 与 Maven
本文分享了 Java 学习中 JDK 安装配置与 Maven 使用的入门知识,涵盖 JDK 下载安装、环境变量设置、Maven 安装配置及本地仓库与镜像设置,帮助新手快速搭建 Java 开发环境。
1836 0
|
安全 Java 微服务
Java 最新技术和框架实操:涵盖 JDK 21 新特性与 Spring Security 6.x 安全框架搭建
本文系统整理了Java最新技术与主流框架实操内容,涵盖Java 17+新特性(如模式匹配、文本块、记录类)、Spring Boot 3微服务开发、响应式编程(WebFlux)、容器化部署(Docker+K8s)、测试与CI/CD实践,附完整代码示例和学习资源推荐,助你构建现代Java全栈开发能力。
1148 1
|
安全 Java API
Java最新技术(JDK 11+) 及以上 Java 最新技术之集合框架实操应用详解
本示例基于Java最新技术(JDK 11+),涵盖集合框架的核心功能,结合Java 8+特性(如Stream API、Lambda表达式)与并发编程最佳实践。内容包括:List操作(初始化、Lambda过滤、Stream处理)、Map操作(流式过滤、ConcurrentHashMap原子操作、并行流)、Set操作(TreeSet排序、CopyOnWriteArraySet并发安全)、Queue/Deque操作(优先队列、双端队列)以及高级聚合操作(集合转换、分组统计、平均值计算)。 [代码下载](https://pan.quark.cn/s/14fcf913bae6)
300 4
|
缓存 网络协议 Java
JAVA网络IO之NIO/BIO
本文介绍了Java网络编程的基础与历史演进,重点阐述了IO和Socket的概念。Java的IO分为设备和接口两部分,通过流、字节、字符等方式实现与外部的交互。
639 0
|
Java API 数据安全/隐私保护
探索Java动态代理的奥秘:JDK vs CGLIB
动态代理是一种在 运行时动态生成代理类的技术,无需手动编写代理类代码。它通过拦截目标方法的调用,实现对核心逻辑的 无侵入式增强(如日志、事务、权限控制等)。
610 0
探索Java动态代理的奥秘:JDK vs CGLIB
|
算法 Java 编译器
深入理解 Java JDK —— 让我们从基础到进阶
JDK(Java Development Kit)是 Java 开发的核心工具包,包含编译、运行和调试 Java 程序所需的所有工具和库。它主要由 JVM(Java 虚拟机)、JRE(Java 运行时环境)和 Java 核心类库组成。JVM 是跨平台运行的基础,负责字节码的加载、执行和内存管理;JRE 提供运行 Java 应用的环境;核心类库则提供了丰富的 API 支持。通过编写、编译和运行一个简单的 Java 程序,可以深入理解 JDK 的工作原理。此外,JDK 还提供了 JIT 编译、垃圾回收优化和并发工具包等高级功能,帮助开发者提高程序性能和稳定性。
2083 10
|
监控 Java API
探索Java NIO:究竟在哪些领域能大显身手?揭秘原理、应用场景与官方示例代码
Java NIO(New IO)自Java SE 1.4引入,提供比传统IO更高效、灵活的操作,支持非阻塞IO和选择器特性,适用于高并发、高吞吐量场景。NIO的核心概念包括通道(Channel)、缓冲区(Buffer)和选择器(Selector),能实现多路复用和异步操作。其应用场景涵盖网络通信、文件操作、进程间通信及数据库操作等。NIO的优势在于提高并发性和性能,简化编程;但学习成本较高,且与传统IO存在不兼容性。尽管如此,NIO在构建高性能框架如Netty、Mina和Jetty中仍广泛应用。
818 3
|
存储 监控 Java
Java的NIO体系
通过本文的介绍,希望您能够深入理解Java NIO体系的核心组件、工作原理及其在高性能应用中的实际应用,并能够在实际开发中灵活运用这些知识,构建高效的Java应用程序。
609 5