java nio FileChannel堆内堆外数据读写全流程分析及使用(附详细流程图)

这里是小奏,觉得文章不错可以关注公众号小奏技术

背景

java nio中文件读写不管是普通文件读写,还是基于mmap实现零拷贝,都离不开FileChannel这个类。

随便打开RocketMQ 源码搜索FileChannel

就可以看到使用频率

kafka也是

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

java文件读写全流程

这里说的仅仅是FileChannel基于堆内存(HeapByteBuffer)的文件读写。

如果是mmap或者堆外内存,可能有些步骤会省略,相当于有一些优化

  1. FileChannel调用read,将HeapByteBuffer拷贝到DirectByteBuffer
  2. JVM在native层使用read系统调用进行文件读取, 这里需要进行上下文切换,从用户态进入内核态
  3. JVM 进程进入虚拟文件系统层,查看文件数据再page cache是否缓存,如果有则直接从page cache读取并返回到DirectByteBuffer
  4. 如果请求文件数据不在page caceh,则进入文件系统。通过块驱动设备进行真正的IO,并进行文件预读,比如读取的文件可能只有1-10,但是会将1-20都读取
  5. 磁盘控制器DMA将磁盘中的数据拷贝到page cache中。这里发生了一次数据拷贝(非CPU拷贝)
  6. CPU将page cache数据拷贝到DirectByteBuffer,因为page cache属于内核空间,JVM进程无法直接寻址。这里是发生第二次数据拷贝
  7. 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

我们继续看看IOUtilwrite方法

可以看到如果是DirectBuffer则可以直接写

如果是HeapByteBuffer则需要转换为DirectByteBuffer

为什么要在DirectByteBuffer做一层转换

主要是HeapByteBuffer受JVM管理,也就是会受到GC影响

如果在进行native调用的时候发生了GC,会导致HeapByteBuffer的内容出现错误

具体详细的说明可以看看这篇MappedByteBuffer VS FileChannel:从内核层面对比两者的性能差异

讲解的非常清晰

参考

  • MappedByteBuffer VS FileChannel:从内核层面对比两者的性能差异

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/648728.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

高奇琦:从大国协调到全球性机制:人工智能大模型全球治理路径探析

内容提要 人工智能大模型全球治理的关键是对大模型进行科学分类。大模型可以分为超大模型和一般模型。对于超大模型的治理,可以参考核武器治理的思路,重点是实现超大模型的有限发展和不扩散。对于一般模型而言,要在安全可控的基础上发挥其对…

昂达固态硬盘数据恢复方法:全面解析与操作指南

在数字化时代,数据已经成为我们生活和工作中不可或缺的一部分。而固态硬盘(SSD)由于其读写速度快、抗震性强等优点,慢慢取代了传统的机械硬盘,成为我们存储数据的主要选择。然而,即便再先进的存储设备&…

OrangePi AIpro初体验之图片视频检测案例真实测评

OrangePi AIpro简介 OrangePi AIpro官网 Orange Pi AI Pro 开发板是香橙派联合华为精心打造的高性能AI 开发板,其搭载了昇腾AI 处理器,可提供8TOPS INT8 的计算能力,内存提供了8GB 和16GB两种版本。可以实现图像、视频等多种数据分析与推理…

网页提示“非私密连接”是为什么?

网页提示“非私密连接”(英文提示可能是 "Your connection is not private" 或 "Your connection is not secure")主要是因为浏览器无法验证你正试图访问的网站的SSL/TLS证书,或者是证书存在问题,从而无法建立…

【机器学习】机器学习在信息安全领域中的典型应用

🚀🚀🚀传送门 🔒机器学习在信息安全领域中的典型应用📕利用机器学习检测恶意行为并阻断攻击🌈使用机器学习分析移动终端安全状况⭐借助机器学习提高信息安全分析水平🎬依靠机器学习自动完成重复…

javaEE—图书管理系统(基础代码版)

前言: 本篇博客是集合了javaEE所学的知识构建的一个基础框架,讲述着面向对象的过程是如何做到多对象交互协作完成框架的构建的。利用了数组,接口,类和对象,抽象类,Object类等知识来完成。 后续会加入数据…

钕铁硼表面磷化处理

大家都知道烧结钕铁硼易氧化、易腐蚀,日久将造成磁性能的衰减甚至丧失,所以使用前必须进行严格的防腐处理。在之前的文章中已经向大家介绍过与烧结钕铁硼表面处理相关的知识和电镀的工艺流程,除了电镀之外,钕铁硼表面处理还可采用…

zstd库数据压缩与解压缩

在 Visual Studio 2019 中使用 C 的 zstd 库进行数据压缩与解压缩 在今天的博客中,我们将探讨如何在 Visual Studio 2019 中使用 zstd 库进行高效的数据压缩和解压缩。zstd(也称为 Zstandard 或 zstd)是由 Facebook 开发的开源压缩库&#x…

数据结构中树的一些基本概念

前言:带你认识二叉树从基本概念开始,步步深入。 目录 树的概念和其中比较重要的基本概念 对概念的深度解析: 树的结构应该如何实现呢? 树的分类: 完全二叉树与满二叉树: 树的概念和其中比较重要的基本…

嵌入式进阶——数码管

🎬 秋野酱:《个人主页》 🔥 个人专栏:《Java专栏》《Python专栏》 ⛺️心若有所向往,何惧道阻且长 文章目录 数码管结构移位寄存器原理图移位寄存器数据流程移位寄存器控制流程移位寄存器串联实现数码管显示 数码管结构 共阴与共阳 共阳数码…

Java SE基础知识(11)

知识梳理: 记不住就看API帮助文档中的pattern类 开发过程中,正则表达式一般不自己写,安装插件any-rule 选择自己想要的正则表达式格式,稍作修改即可

科学提效|AI融入零售业,未来零售的创新之旅

零售业正经历着由人工智能(AI)引领的转型浪潮。AI在零售和消费品(CPG)行业的应用前景广阔,它正以多种创新方式重塑行业的运作模式。且随着技术的不断进步,AI在零售业的应用将变得更加广泛和深入。AI不仅能够…

解锁Facebook的神秘密码:探索社交媒体的奥秘

在当今数字时代,社交媒体已经渗透到我们生活的方方面面。Facebook,作为这个领域中最为瞩目的平台之一,不仅连接着全球数十亿用户,还承载着庞大的信息流和交流网络。然而,Facebook的背后是一个充满着技术和隐私的世界&a…

汇凯金业:纸黄金和实物黄金的价格有什么区别

纸黄金和实物黄金的价格主要受到全球黄金市场行情的影响,二者的基础价格并无太大差异,但在具体交易时,可能会存在一些价格上的区别,这些差异主要来自以下几个方面: 交易费用与管理费:纸黄金交易通常需要支…

Jenkins配置(插件/角色/凭证)

目录 传送门前言一、Jenkins插件管理1、更换为国内下载源2、中文汉化插件下载(不推荐)3、低版本Jenkins爆红插件安装4、低版本Jenkins插件持续报错解决办法 二、Jenkins用户角色三、Jenkins凭证管理(svn/git)1、Username with pas…

k8s集群安装后CoreDNS 启动报错plugin/forward: no nameservers found

安装k8s过程中遇到的问题: 基本信息 系统版本:ubuntu 22.04 故障现象: coredns 报错:plugin/forward: no nameservers found 故障排查: #检查coredns的配置,发现有一条转发到/etc/resolv.conf的配置…

重生奇迹mu增加敏捷的装备

穿龙炎。 1、游戏破坏方面。可以降低"敏捷"的武器,如果你是低敏捷穿龙炎,我推荐你拿它,穿龙炎配的,同时,它的攻击,我感觉是最稳定的。 2、好看方面。通常大家都穿它都是因为好看,但是很多高手也穿他,为什么?因为穿它好配点,高敏捷你可以穿,低敏捷你也可以穿它,视武…

会声会影破解版百度云(附安装教程) 会声会影下载免费中文版 会声会影2024激活码,注册机

会声会影是一款功能强大的视频与电影编辑软件,它拥有出色的色彩校正和视频氛围调整工具。这款软件对颜色、平度HSL调谐、色调曲线以及波形范围等细微变化有着敏锐的感知,能够轻松实现颜色的精确移动和校正。此外,会声会影还提供了丰富的功能&…

【量算分析工具-概述】GeoServer改造Springboot番外系列三

背景概述 GIS公司做软件产品,往往绕不开的是量算分析工具的开发和使用。例如做的比较好的火星科技的mars3d产品,如下图,但是往往这些工具都是利用Cesium框架进行前端计算的实现的,网上关于这些量算工具算法原理的文章少之又少&…

遥感信息SCI期刊,中科院1区,IF=7+,审稿速度非常快!

一、期刊名称 International Journal of Applied Earth Observation and Geoinformation 二、期刊简介概况 期刊类型:SCI 学科领域:遥感 影响因子:7.5 中科院分区:1区 三、期刊征稿范围 《国际应用地球观测和地理信息杂志》…