计算机内存管理

原文链接 https://www.cnblogs.com/guozp/p/10470431.html

MMC:CPU的内存管理单元。

物理内存:即内存条的内存空间。

虚拟内存:计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。

页面文件:操作系统反映构建并使用虚拟内存的硬盘空间大小而创建的文件,在windows下,即pagefile.sys文件,其存在意味着物理内存被占满后,将暂时不用的数据移动到硬盘上。

缺页中断:当程序试图访问已映射在虚拟地址空间中但未被加载至物理内存的一个分页时,由MMC发出的中断。如果操作系统判断此次访问是有效的,则尝试将相关的页从虚拟内存文件中载入物理内存。

MappedByteBuffer介绍

MappedByteBuffer 是Java NIO中引入的一种硬盘物理文件和内存映射方式,当物理文件较大时,采用MappedByteBuffer,读写性能较高,其内部的核心实现是DirectByteBuffer(JVM 堆外直接物理内存)。

JVM 进程通过内存映射方式加载的物理文件并不会耗费同等大小的物理内存。当应用程序访问数据时,程序通过虚拟地址寻址对应的内存页,如果物理内存中不存在对应页,MMU则会产生缺页中断异常,CPU尝试从系统Swap分区中查找,如仍不存在,则会直接从硬盘中物理文件中读取。

传统的基于文件流的方式读取文件方式是系统指令调用,文件数据首先会被读取到进程的内核空间的缓冲区,而后复制到进程的用户空间,这个过程中存在两次数据拷贝;而内存映射方式读取文件的方式,也是系统指令调用,在产生缺页中断后,CPU直接从磁盘文件load数据到进程的用户空间,只有一次数据拷贝。

FileChannel提供了map方法把磁盘文件映射到虚拟内存,通常情况可以映射整个文件,如果文件比较大,可以进行分段映射。

内存映像文件访问的方式,共三种:

    a) MapMode.READ_ONLY:只读,试图修改得到的缓冲区将导致抛出异常。

    b) MapMode.READ_WRITE:读/写,对得到的缓冲区的更改最终将写入文件;但该更改对映射到同一文件的其他程序不一定是可见的。

    c) MapMode.PRIVATE:私用,可读可写,但是修改的内容不会写入文件,只是buffer自身的改变。

MappedByteBuffer在处理大文件时的确性能很高,但也存在一些问题,其所对应的内存使用的是JVM堆外内存,JVM young gc和CMS gc并不能触发回收MappedByteBuffer对应的内存,只有full gc(stop the world的方式)可以使其回收内存,堆外直接内存会根据自己的情况(当需要新分配直接内存时,如果所剩堆外内存空间不够,第一次产生OutOfMemoryError时)来触发 System.gc(),此处有坑,若JVM配置了参数-XX:DisableExplicitGC,System.gc()将不会触发full gc,最终导致内存泄漏。而且触发其内存回收的时间点是不确定的。Java api文档中标注:

A mapped byte buffer and the file mapping that it represents remain valid until the buffer itself is garbage-collected.

在应用程序频繁使用堆外内存时,还可以通过-XX:MaxDirectMemorySize来指定最大的堆外内存大小,当使用达到了阈值的时候将调用System.gc来做一次full gc,以此来回收掉游离状态的堆外内存。

因此,在使用堆外内存高性能的福利的同时,及时的回收掉废弃掉的内存是十分关键的。

性能分析

从代码层面上看,从硬盘上将文件读入内存,都要经过文件系统进行数据拷贝,并且数据拷贝操作是由文件系统和硬件驱动实现的,理论上来说,拷贝数据的效率是一样的。

但是通过内存映射的方法访问硬盘上的文件,效率要比read和write系统调用高,这是为什么?

read()是系统调用,首先将文件从硬盘拷贝到内核空间的一个缓冲区,再将这些数据拷贝到用户空间,实际上进行了两次数据拷贝;

map()也是系统调用,但没有进行数据拷贝,当缺页中断发生时,直接将文件从硬盘拷贝到用户空间,只进行了一次数据拷贝。

所以,采用内存映射的读写效率要比传统的read/write性能高。

总结

MappedByteBuffer使用虚拟内存,因此分配(map)的内存大小不受JVM的-Xmx参数限制,但是也是有大小限制的。

如果当文件超出1.5G限制时,可以通过position参数重新map文件后面的内容。

MappedByteBuffer在处理大文件时的确性能很高,但也存在一些问题,如内存占用、文件关闭不确定,被其打开的文件只有在垃圾回收的才会被关闭,而且这个时间点是不确定的。

javadoc中也提到:A mapped byte buffer and the file mapping that it represents remain* valid until the buffer itself is garbage-collected.

原文链接 https://www.cnblogs.com/guozp/p/10470431.html

MappedByteBuffer的更多相关文章

  1. Java--Stream,NIO ByteBuffer,NIO MappedByteBuffer性能对比

    目前Java中最IO有多种文件读取的方法,本文章对比Stream,NIO ByteBuffer,NIO MappedByteBuffer的性能,让我们知道到底怎么能写出性能高的文件读取代码. pack ...

  2. Atitit.病毒木马的快速扩散机制原理nio 内存映射MappedByteBuffer

    Atitit.病毒木马的快速扩散机制原理nio 内存映射MappedByteBuffer 1. Java NIO(New Input/Output)1 1.1. 变更通知(因为每个事件都需要一个监听者 ...

  3. Java NIO教程 MappedByteBuffer

    之前跟大家说过,要讲MappedByteBuffer,现在我来履行承诺了. 首先从大体上讲一下MappedByteBuffer究竟是什么.从继承结构上来讲,MappedByteBuffer继承自Byt ...

  4. MappedByteBuffer读写文件

    一. MappedByteBuffer java把文件映射到内存中,避免堆内存产生大对象引起full gc.mappedByteBuffer的读写速度都要超过堆内读写文件的速度 public clas ...

  5. RandomAcessFile、MappedByteBuffer和缓冲读/写文件

    项目需要进行大文件的读写,调查测试的结果使我决定使用MappedByteBuffer及相关类进行文件的操作,效果不是一般的高. 网上参考资源很多,如下两篇非常不错: 1.花1K内存实现高效I/O的Ra ...

  6. MappedByteBuffer高速缓存文件、RandomAccessFile随机访问

    说到高速缓存存储,处理读写文件,那就不得不说MappedByteBuffer. 看了好多文章以后写一下自己的总结. 在这里先介绍一下相关的类与方法. 先说一下Buffer.ByteBuffer.Map ...

  7. Java NIO之内存映射文件——MappedByteBuffer

    大多数操作系统都可以利用虚拟内存实现将一个文件或者文件的一部分"映射"到内存中.然后,这个文件就可以当作是内存数组来访问,这比传统的文件要快得多. 内存映射文件的一个关键优势是操作 ...

  8. Kafka-4614问题复盘 (MappedByteBuffer未关闭导致慢磁盘访问)

    很早之前就想动笔就这个kafka bug总结一番了,只是这个问题既不是本人发现,也不是自己动手修复,终归是底气不足,故而一直耽搁下来.怎奈此问题实在是含金量十足,又恰逢最近有人询问Kafka 0.10 ...

  9. Java RandomAccessFile与MappedByteBuffer

    Java RandomAccessFile与MappedByteBuffer https://www.cnblogs.com/guazi/p/6838915.html

随机推荐

  1. 一个js小游戏----总结

    花了大概一天左右的功夫实现了一个js小游戏的基本功能,类似于“雷电”那样的小游戏,实现了随即怪物发生器,碰撞检测,运动等等都实现了,下一个功能是子弹轨迹,还有其他一些扩展功能,没有用库,也没有用web ...

  2. python教你用微信每天给女朋友说晚安

    但凡一件事,稍微有些重复.我就考虑怎么样用程序来实现它. 这里给各位程序员朋友分享如何每天给朋友定时微信发送"晚安",故事,新闻,等等··· ···最好运行在服务器上,这样后台挂起 ...

  3. 知识点:java一些方法会有横线?以Date 过期方法为例

    原因:他们的开发者在升级方法后,添加了@Deprecated注释, 目的是为了提醒我们,这个方法现在已经有新的方法了,不建议继续使用! 比如: JAVA中Date的tolocalstring为什么不建 ...

  4. Eclipse中启动tomcat: java.lang.OutOfMemoryError: PermGen space的解决方法

    tomcat启动的时候出现这种错误一般是项目引用了太多的jar包,或者反射生成了太多的类,或者有太多的常量池,导致非堆内存中永久保存区域不够,就有可能会报java.lang.OutOfMemoryEr ...

  5. 蓝鲸 CTF web——密码泄露

    今天才知道还有蓝鲸安全这个平台,又涨了一点知识,我来分享一下个人的解题思路以及感受,希望能够帮助到那些需要的人 (我想把每一步都写下来,因为我还是萌新,所以我知道有可能会因为一步的不会导致所有都不会的 ...

  6. i春秋----Misc

    好久没有写 博客今天更新多了一些 解题思路:题目做多了,自然能够想到是凯撒解密: 查看得到答案; flag{4c850c5b3b2756e67a91bad8e046dda} 2: 解题思路:是我想太多 ...

  7. OsharpNS轻量级.net core快速开发框架简明入门教程-Osharp.Redis使用

    OsharpNS轻量级.net core快速开发框架简明入门教程 教程目录 从零开始启动Osharp 1.1. 使用OsharpNS项目模板创建项目 1.2. 配置数据库连接串并启动项目 1.3. O ...

  8. 线上应用调试利器 --Arthas

    在之前的文章中,我介绍了使用 Btrace 工具进行线上代码的debug (https://www.cnblogs.com/yougewe/p/10180483.html),其大致原理就是通过字节码注 ...

  9. 干货|一个案例学会Spring Security 中使用 JWT

    在前后端分离的项目中,登录策略也有不少,不过 JWT 算是目前比较流行的一种解决方案了,本文就和大家来分享一下如何将 Spring Security 和 JWT 结合在一起使用,进而实现前后端分离时的 ...

  10. 『OGG 02』Win7 配置 Oracle GoldenGate Adapter Java 踩坑指南

    上一文章 <__Win7 配置OGG(Oracle GoldenGate).docx>定下了 两个目标: 目标1: 给安装的Oracle_11g 创建 两个用户 admin 和 root ...