Java内存映射原理与实现

Java内存映射原理与实现Java虚拟机规范中定义了Java内存模型(JavaMemoryModel,JMM),用于屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的并发效果,JMM规范了Java虚拟机与计算机内存是如何协同工作的:规定了一个线程如何和何时可以看到由其他线程修改过后的共享变量的值,以及在必须时如何同步的访问共享变量。

大家好,又见面了,我是你们的朋友全栈君。

01. 虚拟内存与内存映射文件

1.1. 概念

  • 虚拟内存
    虚拟内存属于硬盘的一部分,是计算机RAM与硬盘的数据交换分区。

    由于实际的物理内存远小于进程的地址空间,这就需要把内存中暂时不用到的数据放到硬盘上一个特殊的地方,当请求的数据不在内存中时,系统产生却页中断,内存管理器便将对应的内存页重新从硬盘调入物理内存。

  • 内存映射文件
    内存映射文件是由一个文件到一块内存的映射。

    应用程序可以通过内存指针对磁盘上的文件进行访问,就如同访问加载了文件的内存,因此内存文件映射非常适合于用来管理大文件。

1.2 区别

  • 磁盘文件
    虚拟内存使用的硬盘只能是页面文件
    内存映射使用的磁盘可以是任何磁盘文件。
  • 架构
  1. 虚拟内存是架构在物理内存之上。

    引入原因:实际的物理内存运行程序所需的空间。即使现在计算机中的物理内存越来越大,程序的尺寸也在增长,将所有运行着的程序全部加载到内存中不经济也非常不现实。

  2. 内存映射文件架构在程序的地址空间之上

    32位机地址空间只有4G,而某些大文件的尺寸可要要远超出这个值,因此,用地址空间中的某段应用文件中的一部分可解决处理大文件的问题,在32中,使用内存映射文件可以处理2的64次(64EB)大小的文件.原因内存映射文件,除了处理大文件,还可用作进程间通信。

02. 内存映射文件的原理

“映射”就是建立一种对应关系,主要是指硬盘上文件的位置与进程逻辑地址空间中一块相同区域之间一一对应。这种关系纯属是逻辑上的概念,物理上是不存在的,原因是进程的逻辑地址空间本身就是不存在的,在内存映射过程中,并没有实际的数据拷贝,文件没有被载入内存,只是逻辑上放入了内存,具体到代码,就是建立并初始化了相关的数据结构,这个过程有系统调用mmap()实现,所以映射的效率很高。
在这里插入图片描述
上面说到建立内存映射没有进行实际的数据拷贝,那么进程又怎么能最终通过内存操作访问到硬盘上的文件呢?

  1. 调用mmap(),相当于要给内存映射文件分配了虚拟内存,它会返回一个指针ptr,这个ptr所指向的是一个逻辑地址,要操作其中的数据,必须通过MMU(Memory Management Unit,即内存管理单元)将逻辑地址转换成物理地址,如图1中过程2所示。
  2. 建立内存映射并没有实际拷贝数据,这时MMU在地址映射表中是无法找到与ptr相对应的物理地址的,也就是MMU失败,将产生一个缺页中断,缺页中断的中断响应函数会在swap(也就是交换分区)中寻找相对应的页面,如果找不到(也就是该文件从来没有被读入内存的情况),则会通过mmap()建立的映射关系,从硬盘上将文件读取到物理内存中,如图1中过程3所示。
  3. 如果在拷贝数据时,发现物理内存不够用,则会通过虚拟内存机制(swap)将暂时不用的物理页面交换到硬盘上,如图1中过程4所示。

03. 内存映射文件的效率

了解过内存映射文件都知道,它比传统的IO读写数据快很多,那么,它为什么会这么快,从代码层面上来看,从硬盘上将文件读入内存,都是要经过数据拷贝,并且数据拷贝操作是由文件系统和硬件驱动实现的,理论上来说,拷贝数据的效率是一 样的。其实,原因是read()是系统调用,其中进行了数据拷贝,它首先将文件内容从硬盘拷贝到内核空间的一个缓冲区,如图2中过程1,然后再将这些数据拷贝到用户空间,如图2中过程2,在这个过程中,实际上完成 了两次数据拷贝 ;而mmap()也是系统调用,如前所述,mmap()中没有进行数据拷贝,真正的数据拷贝是在缺页中断处理时进行的,由于mmap()将文件直接映射到用户空间,所以中断处理函数根据这个映射关系,直接将文件从硬盘拷贝到用户空间,只进行了 一次数据拷贝 。因此,内存映射的效率要比read/write效率高。
在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/151749.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 全排列 leetcode_8的全排列

    全排列 leetcode_8的全排列给定一个没有重复数字的序列,返回其所有可能的全排列。示例:输入:[1,2,3]输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]classSolution:defpermute(self,nums):res=[]defbackt…

    2022年9月20日
  • ES6模板字符串`的引用

    ES6模板字符串`的引用传统的JavaScript语言,输出模板通常是这样写的(下面使用了jQuery的方法)。$(‘#result’).append(‘Thereare<b>’+basket.count+'</b>’+’itemsinyourbasket,’+'<em>’+basket.onSale+'</em>areonsale!’);上面这种写法相当繁琐不方便,ES6引入了模板字符串解决这个问题。

    2022年8月21日
  • pycharm安装python3.6_python3.8怎么安装

    pycharm安装python3.6_python3.8怎么安装1.软件准备Python开发环境3.6以上PyCharm编辑器 Python开发环境3.6以上 浏览器谷歌最新版 浏览器驱动与浏览器版本匹配*资源包获取链接:https://pan.baidu.com/s/10n7MfZXtRNWnXJghT9xq2g提取码:w8mm 安装PyCharm 双击下载好的安装包“pycharm-community-2020.2.3.exe”,一路“Next”即可完成安装,可以修改默认安装路径。 安装P…

    2022年8月26日
  • asp.net gridview_net core mvc 怎么做增删改查

    asp.net gridview_net core mvc 怎么做增删改查在ASP.NETMVC3中,WebGrid是 Web.Helpers下的新的类,使用WebGrid可以减小我们的代码量,本篇先简单的看下WebGrid的使用方法,包括它的分页、排序功能以及样式的设置等。我们还是从留言表读取数据,并使用WebGrid来展示我们的留言。WebGrid大体原理就是将数据集合组织输出一个HTML表格,使用WebGrid我们先创建一个

    2022年10月5日
  • mybatis log 激活码(注册激活)

    (mybatis log 激活码)本文适用于JetBrains家族所有ide,包括IntelliJidea,phpstorm,webstorm,pycharm,datagrip等。IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html…

    2022年3月27日
  • PCA算法过程_pca推导

    PCA算法过程_pca推导PCA是主成分分析(PrincipalComponentsAnalysis)的简称。这是一种数据降维技术,用于数据预处理。一般我们获取的原始数据维度都很高,那么我们可以运用PCA算法降低特征维度。这样不仅可以去除无用的噪声,还能减少很大的计算量。…

    2022年11月1日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号