java nio FileChannel堆内堆外数据读写全流程分析及使用(附详细流程图)
这里是小奏,觉得文章不错可以关注公众号小奏技术
背景
java nio中文件读写不管是普通文件读写,还是基于mmap实现零拷贝,都离不开FileChannel这个类。
随便打开RocketMQ 源码搜索FileChannel
就可以看到使用频率

kafka也是

所以在java中文件读写FileChannel尤为重用
java文件读写全流程

这里说的仅仅是FileChannel基于堆内存(HeapByteBuffer)的文件读写。
如果是mmap或者堆外内存,可能有些步骤会省略,相当于有一些优化
FileChannel调用read,将HeapByteBuffer拷贝到DirectByteBuffer- JVM在
native层使用read系统调用进行文件读取, 这里需要进行上下文切换,从用户态进入内核态 - JVM 进程进入虚拟文件系统层,查看文件数据再
page cache是否缓存,如果有则直接从page cache读取并返回到DirectByteBuffer - 如果请求文件数据不在
page caceh,则进入文件系统。通过块驱动设备进行真正的IO,并进行文件预读,比如读取的文件可能只有1-10,但是会将1-20都读取 - 磁盘控制器DMA将磁盘中的数据拷贝到
page cache中。这里发生了一次数据拷贝(非CPU拷贝) - CPU将
page cache数据拷贝到DirectByteBuffer,因为page cache属于内核空间,JVM进程无法直接寻址。这里是发生第二次数据拷贝 - JVM进程从内核态切换回用户态,这里如果使用的是堆内存(
HeapByteBuffer),实际还需要将堆外内存DirectByteBuffer拷贝到堆内存(HeapByteBuffer)
FileChannel读写文件(非MMAP)
public static void main(String[] args) {String filename = "小奏技术.txt";String content = "Hello, 小奏技术.";// 写入文件writeFile(filename, content);// 读取文件System.out.println("Reading from file:");readFile(filename);}public static void writeFile(String filename, String content) {// 创建文件对象File file = new File(filename);// 确保文件存在if (!file.exists()) {try {boolean created = file.createNewFile();if (!created) {System.err.println("Unable to create file: " + filename);return;}} catch (Exception e) {System.err.println("An error occurred while creating the file: " + e.getMessage());return;}}// 使用FileChannel写入文件try (RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");FileChannel fileChannel = randomAccessFile.getChannel()) {ByteBuffer buffer = ByteBuffer.allocate(content.getBytes().length);buffer.put(content.getBytes());buffer.flip(); // 切换到读模式while (buffer.hasRemaining()) {fileChannel.write(buffer);}} catch (Exception e) {System.err.println("An error occurred while writing to the file: " + e.getMessage());}}public static void readFile(String filename) {// 使用FileChannel读取文件try (RandomAccessFile randomAccessFile = new RandomAccessFile(filename, "r");FileChannel fileChannel = randomAccessFile.getChannel()) {ByteBuffer buffer = ByteBuffer.allocate((int) fileChannel.size());while (fileChannel.read(buffer) > 0) {// Do nothing, just read}// 切换到读模式buffer.flip(); /* while (buffer.hasRemaining()) {System.out.print((char) buffer.get());}*/Charset charset = StandardCharsets.UTF_8; String fileContent = charset.decode(buffer).toString();System.out.print(fileContent);} catch (Exception e) {System.err.println("An error occurred while reading the file: " + e.getMessage());}}
这里需要注意的一个细节
我们分配的内存的方式是
ByteBuffer.allocate()
这里我们可以进入看看源码

实际构造的是HeapByteBuffer,也就是JVM的堆内存
如果我们使用
ByteBuffer.allocateDirect()

则构造的是堆外内存DirectByteBuffer
HeapByteBuffer和DirectByteBuffer文件读写区别
我们看看FileChannel read方法

发现IO相关的处理被封装在IOUtil
我们继续看看IOUtil的write方法

可以看到如果是DirectBuffer则可以直接写
如果是HeapByteBuffer则需要转换为DirectByteBuffer

为什么要在DirectByteBuffer做一层转换
主要是HeapByteBuffer受JVM管理,也就是会受到GC影响
如果在进行native调用的时候发生了GC,会导致HeapByteBuffer的内容出现错误
具体详细的说明可以看看这篇MappedByteBuffer VS FileChannel:从内核层面对比两者的性能差异
讲解的非常清晰
参考
- MappedByteBuffer VS FileChannel:从内核层面对比两者的性能差异
相关文章:
java nio FileChannel堆内堆外数据读写全流程分析及使用(附详细流程图)
这里是小奏,觉得文章不错可以关注公众号小奏技术 背景 java nio中文件读写不管是普通文件读写,还是基于mmap实现零拷贝,都离不开FileChannel这个类。 随便打开RocketMQ 源码搜索FileChannel 就可以看到使用频率 kafka也是 所以在java中文件读写FileCh…...
微服务架构-分支微服务设计模式
微服务架构-分支微服务设计模式 这种模式是聚合器模式的扩展,允许同时调用两个微服务链 分支微服务设计模式是一种用于构建大型系统的微服务架构模式,其核心思想是 将复杂的业务逻辑拆解为多个小的、相互独立的子系统,每个子系统由一个或多…...
关于Vue本地图片转file传到后端服务器(不通过组件上传)
一、代码 // 核心代码 const getMyFileFromLocalPath (localPath, filename) > {return fetch(localPath).then((response) > response.blob()).then((blob) > new File([blob], filename, { type: "image/png" })); // 假设是PNG格式// 获取真正的流文件…...
CCF20240302——相似度计算
CCF20240302——相似度计算 代码如下: #include <stdio.h> #include <string.h> #include <ctype.h>#define MAX_WORD_LEN 100 #define MAX_WORDS 10000int main() {int n, m;scanf("%d %d", &n, &m);char words1[MAX_WORDS][…...
C++的第一道门坎:类与对象(二)
一.类中生成的默认成员函数详解 0.类的6个默认成员函数 编译器会给类生成六个默认成员函数,在类中即使我们什么都不做,也会自动生成。 默认成员函数:用户没有显式实现,编译器会自动生成的成员函数称为默认成员函数。 下面我们逐…...
C语言与内存息息相关的重要概念有哪些?
一、问题 C语⾔、C语⾔和C#语⾔,这三门语⾔,⼀个⽐⼀个加号()多,C语⾔没有加号,C有两个加号,C#有四个加号。随着语⾔的发展,⼀个⽐⼀个简单,很多问题系统都给做了&#x…...
【chagpt】广泛使用API之前:考虑成本和数据隐私
文章目录 一. 定价和标记限制二. 安全和隐私 在广泛使用API之前,应该考虑两个重要因素:成本和数据隐私。 一. 定价和标记限制 OpenAI在Pricing页面上列出了模型的定价。请注意,OpenAI不一定及时更新该页面上的定价信息,因此实际…...
六月后考研如何备考看这一篇就够了
以下是考研六月后可以参考的规划: 6 月至 8 月(强化阶段): 英语:继续背单词,开始刷历年真题中的阅读部分,仔细分析错题原因,总结解题技巧。数学:完成基础阶段的复习后&am…...
Linux主机连接腾讯云服务器详细配置
硬件条件 当然你要先有一个云服务器,腾讯云比阿里云便宜一点,所以就用腾讯云了 问了师兄买这个98的就行,选择CentOS,不要选Ubuntu,因为 嗯,大概就是这样 编程测试 云服务器当然是作为服务端 server.cpp…...
数字化工厂怎么收集,处理数据?
数字化工厂的数据收集与处理 数字化工厂是现代化工厂,利用数字技术和数据分析提高效率和优化流程。数据分析作为数字化工厂的核心技术,对数据的获取与处理至关重要。在数字化工厂中,数据的来源包括企业内部信息系统、物联网信息以及外部信息&…...
OOM不会导致JVM退出
问题来源 一次生产事故,由于一次性从数据库查询过多数据导致线程 OOM:Java heap space 异常(千万级表,JVM堆内存2G),但是在线程OOM发生时,java进程却没有立即挂掉。 ##OOM与异常 说到底OutOfM…...
C++学习日记 | LAB 6 static library 静态库
资料来源:南科大 余仕琪 C/C Program Design LINK:CPP/week06 at main ShiqiYu/CPP GitHub 一、本节内容 本节主要介绍静态库和动态库。 1.1 静态库和动态库的概念 静态链接和静态库(也称为存档)是链接器将所有使用的库函数复制到可执行文件的结果。静…...
他用AI,抄袭了我的AI作品
《大话西游》里面有一句经典台词:每个人都有一个妈,但是“你妈就一定是你妈吗?” 用AI创作的艺术作品,也走进类似的困境:如何证明你用AI生成的作品,就是你的作品? 近日,腾讯科技独…...
力扣刷题--2956. 找到两个数组中的公共元素【简单】
题目描述 给你两个下标从 0 开始的整数数组 nums1 和 nums2 ,它们分别含有 n 和 m 个元素。 请你计算以下两个数值: 统计 0 < i < n 中的下标 i ,满足 nums1[i] 在 nums2 中 至少 出现了一次。 统计 0 < i < m 中的下标 i &am…...
海信集团携纷享销客启动LTC数字化落地 推动ToB业务再升级
日前,海信集团携手连接型CRM纷享销客正式启动LTC(Leads to Cash)数字化平台实施落地项目。作为海信集团数字化的重要里程碑,该项目将通过统一规划、统一投资、统一平台、资源共享和数据赋能,构建ToB业务数字化经营管理…...
【Go语言入门学习笔记】Part5.函数
一、前言 这里的还是跟C有区别的,大家熟悉了其他语言后,还得注意一下这里的内容。Go的函数非常灵活。 二、学习代码 package mainimport "fmt"// ZhengXing 类似typedef的方法 type ZhengXing int// 函数名有说法,首字母大写是pu…...
磁珠笔记汇总
磁珠笔记汇总 磁珠是和电感很相似的器件。 电感磁珠单位亨(H)欧姆(Ω)是否储能存储能量消耗高频能量应用场景通常用于开关电源吸收高频,EMC保护如何看待损耗使用电感时希望损耗越小越好使用磁珠时是利用其损耗来消耗不需要的高频分量 一、磁珠的工作原理 磁珠与…...
【css3】02-css3新特性之选择器篇
目录 1 属性选择器 2 结构伪类选择器 3 其他选择器 :target和::selection ::first-line和::first-letter 4 伪类和伪元素的区别 伪类(Pseudo-classes) 伪元素(Pseudo-elements) 伪类和伪元素的区别 1 属性选择器 ☞ 属性选…...
修正错误的插入排序
错误版 void InsertSort(vector<int>& nums) {for (int i 0; i < nums.size()-1; i){int end i;int t nums[end 1];while (end > 0){if (nums[end1] < nums[end]) nums[end 1] nums[end];else break;--end;}nums[end 1] t;} } 无法得到正确结果。…...
Unity 权限 之 Android 【权限 动态申请】功能的简单封装
Unity 权限 之 Android 【权限 动态申请】功能的简单封装 目录 Unity 权限 之 Android 【权限 动态申请】功能的简单封装 一、简单介绍 二、Android 权限 动态申请 三、实现原理 四、注意事项 五、案例实现简单步骤 附录: 一、进一步优化 二、多个权限申请…...
从‘硬’开关到‘软’启动:拆解一个经典PMOS缓启动电路,聊聊D4、D6这些二极管到底在忙啥?
从‘硬’开关到‘软’启动:拆解一个经典PMOS缓启动电路,聊聊D4、D6这些二极管到底在忙啥? 在硬件设计中,电源管理电路如同交响乐团的指挥,协调着各个器件的动作节奏。而缓启动电路,则是这位指挥手中那根至关…...
LingBot-Depth效果实测:与传感器原生深度对比的绝对误差(mm)分布图
LingBot-Depth效果实测:与传感器原生深度对比的绝对误差(mm)分布图 1. 引言:当深度图遇上“脑补”大师 想象一下,你手里有一张用深度相机拍出来的照片,它告诉你每个像素离相机有多远。但问题是࿰…...
SpringBoot + MongoDB 5分钟快速集成:从0到1实操指南
目录 MongoDB 快速集成 常用API MongoDB MongoDB 是一个基于分布式文件存储的文档型数据库,属于 NoSQL 数据库中最接近关系型数据库的产品,旨在为 Web 应用提供高性能、高可用和可扩展的数据存储解决方案 。 MongoDB以灵活的无模式文档模型…...
PN5180 ISO15693协议栈实现与嵌入式NFC开发指南
1. PN5180库深度解析:面向嵌入式工程师的NFC ISO15693协议栈实现指南NXP PN5180是业界领先的多协议NFC控制器,支持ISO/IEC 14443 A/B、ISO/IEC 15693、Felica及NFC Forum Type 1–5标签。其核心优势在于高集成度射频前端、可编程调制解调器及灵活的主机接…...
运算放大器与比较器的本质区别及应用指南
1. 运算放大器与比较器的本质区别在电子电路设计中,运算放大器(Op-Amp)和电压比较器(Comparator)是两种极为常见却又经常被混淆的器件。它们在外观符号上几乎一模一样:都有五个引脚——正负电源端、同相与反…...
AD5144A数字电位器I²C驱动库深度解析与工程实践
1. AD5144A数字电位器驱动库深度解析:面向嵌入式工程师的IC控制实践指南AD5144A是ADI公司推出的四通道非易失性数字电位器,属于AD51xx系列中功能完备、应用灵活的代表型号。该器件通过IC接口实现对四个独立通道的精确电阻调节,支持256级&…...
cv2.findContours()错误的解决办法ValueError: not enough values to unpack (expected 3, got 2)
方法一:直接去掉一个返回值就即可。 方法二:把OpenCV 安装3.X的版本 具体原因 2、解析差异: OpenCV2和OpenCV4中: findContours这个轮廓提取函数会返回两个值:①轮廓的点集(contours)②各层轮廓的索引(hierarchy) 返回…...
Vue3+ECharts水球图实战:手把手教你打造个性化数据展示组件
Vue3与ECharts水球图深度整合:打造企业级数据可视化组件 在数据驱动的时代,可视化呈现已成为现代Web应用的核心竞争力。水球图(Liquid Fill Chart)作为一种直观展示百分比数据的可视化形式,在仪表盘、进度监控和数据看…...
ArcGIS Pro脚本工具实战:一键自动化面要素数据质量检查与修复
1. 为什么需要自动化面要素质检工具 在GIS数据处理工作中,面要素的质量检查是个绕不开的痛点。我做过不少国土调查和城市规划项目,每次拿到甲方提供的原始数据,光是检查拓扑错误就得花上大半天。传统的手动检查流程有多繁琐呢?你得…...
3步颠覆文献管理:让Zotero格式修复效率提升10倍的实战指南
3步颠覆文献管理:让Zotero格式修复效率提升10倍的实战指南 【免费下载链接】zotero-format-metadata Linter for Zotero. A plugin for Zotero to format item metadata. Shortcut to set title rich text; set journal abbreviations, university places, and item…...
