Java文件读写原理和虚拟内存

简介:  后面打算系统性的介绍下NIO和Netty的内容,因为这块内容也是每个程序员必须要掌握的内容,而在介绍NIO之前我们需要先了解下一些前置的知识


 后面打算系统性的介绍下NIO和Netty的内容,因为这块内容也是每个程序员必须要掌握的内容,而在介绍NIO之前我们需要先了解下一些前置的知识

1.内核空间和用户空间

 这两个概念对于初次接触的小伙伴来说并不是很好理解,举个简单例子如下图:

image.png

 上图中的储户是没法直接从金库中存钱获取取钱的,如果这么做了,那么就非法了。这里用户空间相当于储户,内核空间相当于银行职员,而硬盘相当于金库,也就是用户空间中的进程没法直接操作读写硬盘中的数据,我们需要通过内核空间来处理,这样对于这两个概念应该会容易理解些。

image.png

2.普通IO操作

 了解了用户空间和内核空间的概念和作用后我们来看下普通IO的执行原理。

image.png

 根据上图,当进程请求一个I/O操作,它会执行一个系统(open() , read() , writer() , close())调用将控制权移交给内核。当内核以这种方式被调用,它随即采取任何必要步骤,找到进程所需数据,并把数据传送到用户空间内指定的缓冲区中,这时常规进程就可以对缓冲区中的数据处理操作了,而内核试图对数据进行高速缓存或预读取,因此进程所需数据可能已经在内核空间里了,如果是这样,该数据只需简单地拷贝出来即可,如果数据不在内核空间,则进程被挂起,内核着手把数据读进内场。

问题

 数据从内核空间拷贝到用户空间似乎多余,为什么不直接让磁盘把数据送到用户空间的缓冲区呢?

   硬盘通常不能直接访问用户空间

   磁盘基于块存储的硬件设备操作的固定大小的数据块,用户进程请求的可能是任意大小或者非对齐的数据块,在这两者数据交互过程中内核负责数据的分解、再组合工作,起到一个中间人的角色。

3.虚拟内存

 通过上面的介绍,我们知道当应用程序需要读取文件的时候,内核首先通过DMA技术将文件内容从磁盘读入内核中的buffer,然后Java应用进程再从内核的buffer将数据读取到应用程序的buffer。也就是有两次的文件复制,为了提升I/O效率和处理能力,操作系统采用虚拟内存的机制。虚拟内存意为使用虚假(或虚拟)地址取代物理(硬件RAM)内存地址。这样做好处颇多,总结起来可分为两大类:

   一个以上的虚拟地址可指向同一个物理内存地址。

   虚拟内存空间可大于实际可用的硬件内存

image.png

 这样做的好处是省去了内核与用户空间的往来拷贝。

3.1 一个以上的虚拟地址可指向同一个物理内存地址

 在进行IO操作时就可以将用户空间的buffer区和内核空间的buffer区指向同一个物理内存。这样用户空间的程序就不需要再去内核空间再取回数据,而是可以直接访问,节省内存空间。

image.png

3.2 虚拟内存空间可大于实际可用的硬件内存

 当用户程序访问内存地址时,一般的操作如下:首先虚拟内存系统会到物理内存去查找该虚拟地址是否存在。如果存在,如A1,则直接从物理内存中读取;如果不存在,如A4则会抛出一个信号。这时虚拟内存系统会去磁盘空间中找,找到后再按一定的策略,将其置入到内存中,如将B2和A4交换。然后由用户程序就可以使用A4中的数据。这样就保证了用户程序可以读取一些大型的文件。

image.png

 从本质上说,物理内存充当了分页区的高速缓存;而所谓分页区,即从物理内存置换出来,转而存储于磁盘上的内存页面.

 把内存页大小设定为磁盘块大小的倍数,这样内核就可直接向磁盘控制硬件发布命令,把内存页写入磁盘,在需要时再重新装入。结果是,所有磁盘 I/O 都在页层面完成。对于采用分页技术的,现代操作系统而言,这也是数据在磁盘与物理内存之间往来的唯一方式

image.png

3.3内存管理单元

 现代 CPU 包含一个称为内存管理单元(MMU)的子系统,逻辑上位于CPU 与物理内存之间。该设备包含虚拟地址向物理内存地址转换时所需映射信息。当 CPU 引用某内存地址时,MMU负责确定该地址所在页(往往通过对地址值进行移位或屏蔽位操作实现),并将虚拟页号转换为物理页号(这一步由硬件完成,速度极快)。如果当前不存在与该虚拟页形成有效映射的物理内存页,MMU会向CPU 提交一个页错误。

image.png

 页错误随即产生一个陷阱(类似于系统调用),把控制权移交给内核,附带导致错误的虚拟地址信息,然后内核采取步骤验证页的有效性。内核会安排页面调入操作,把缺失的页内容读回物理内存。这往往导致别的页被移出物理内存,好给新来的页让地方。在这种情况下,如果待移出的页已经被碰过了(自创建或上次页面调入以来,内容已发生改变),还必须首先执行页面调出,把页内容拷贝到磁盘上的分页区。

 如果所要求的地址不是有效的虚拟内存地址(不属于正在执行的进程的任何一个内存段),则该页不能通过验证,段错误随即产生。于是,控制权转交给内核的另一部分,通常导致的结果就是进程被强令关闭。

 一旦出错的页通过了验证,MMU 随即更新,建立新的虚拟到物理的映射(如有必要,中断被移出页的映射),用户进程得以继续。造成页错误的用户进程对此不会有丝毫察觉,一切都在不知不觉中进行


相关文章
|
26天前
|
Java 大数据 Go
从混沌到秩序:Java共享内存模型如何通过显式约束驯服并发?
并发编程旨在混乱中建立秩序。本文对比Java共享内存模型与Golang消息传递模型,剖析显式同步与隐式因果的哲学差异,揭示happens-before等机制如何保障内存可见性与数据一致性,展现两大范式的深层分野。(238字)
46 4
|
30天前
|
存储 缓存 Java
【深入浅出】揭秘Java内存模型(JMM):并发编程的基石
本文深入解析Java内存模型(JMM),揭示synchronized与volatile的底层原理,剖析主内存与工作内存、可见性、有序性等核心概念,助你理解并发编程三大难题及Happens-Before、内存屏障等解决方案,掌握多线程编程基石。
|
1月前
|
Java Unix Go
【Java】(8)Stream流、文件File相关操作,IO的含义与运用
Java 为 I/O 提供了强大的而灵活的支持,使其更广泛地应用到文件传输和网络编程中。!但本节讲述最基本的和流与 I/O 相关的功能。我们将通过一个个例子来学习这些功能。
140 1
|
2月前
|
安全 Java 应用服务中间件
Spring Boot + Java 21:内存减少 60%,启动速度提高 30% — 零代码
通过调整三个JVM和Spring Boot配置开关,无需重写代码即可显著优化Java应用性能:内存减少60%,启动速度提升30%。适用于所有在JVM上运行API的生产团队,低成本实现高效能。
222 3
|
2月前
|
缓存 监控 Kubernetes
Java虚拟机内存溢出(Java Heap Space)问题处理方案
综上所述, 解决Java Heap Space溢出需从多角度综合施策; 包括但不限于配置调整、代码审查与优化以及系统设计层面改进; 同样也不能忽视运行期监控与预警设置之重要性; 及早发现潜在风险点并采取相应补救手段至关重要.
459 17
|
3月前
|
存储 监控 算法
Java垃圾回收机制(GC)与内存模型
本文主要讲述JVM的内存模型和基本调优机制。
|
3月前
|
存储 缓存 Java
Java数组全解析:一维、多维与内存模型
本文深入解析Java数组的内存布局与操作技巧,涵盖一维及多维数组的声明、初始化、内存模型,以及数组常见陷阱和性能优化。通过图文结合的方式帮助开发者彻底理解数组本质,并提供Arrays工具类的实用方法与面试高频问题解析,助你掌握数组核心知识,避免常见错误。
|
3月前
|
边缘计算 算法 Java
Java 绿色计算与性能优化:从内存管理到能耗降低的全方位优化策略与实践技巧
本文探讨了Java绿色计算与性能优化的技术方案和应用实例。文章从JVM调优(包括垃圾回收器选择、内存管理和并发优化)、代码优化(数据结构选择、对象创建和I/O操作优化)等方面提出优化策略,并结合电商平台、社交平台和智能工厂的实际案例,展示了通过Java新特性提升性能、降低能耗的显著效果。最终指出,综合运用这些优化方法不仅能提高系统性能,还能实现绿色计算目标,为企业节省成本并符合环保要求。
125 0
|
3月前
|
监控 Kubernetes Java
最新技术栈驱动的 Java 绿色计算与性能优化实操指南涵盖内存优化与能效提升实战技巧
本文介绍了基于Java 24+技术栈的绿色计算与性能优化实操指南。主要内容包括:1)JVM调优,如分代ZGC配置和结构化并发优化;2)代码级优化,包括向量API加速数据处理和零拷贝I/O;3)容器化环境优化,如K8s资源匹配和节能模式配置;4)监控分析工具使用。通过实践表明,这些优化能显著提升性能(响应时间降低40-60%)同时降低资源消耗(内存减少30-50%,CPU降低20-40%)和能耗(服务器功耗减少15-35%)。建议采用渐进式优化策略。
173 1