我们写一个测试程序:

public static void main(String[] args) throws Exception {
RandomAccessFile randomAccessFile = new RandomAccessFile("./FileMmapTest.txt", "rw");
FileChannel channel = randomAccessFile.getChannel();
MappedByteBuffer []mappedByteBuffers = new MappedByteBuffer[5]; //开5个相同文件的MappedByteBuffer,但是实际机器内存只有8G
mappedByteBuffers[0] = channel.map(FileChannel.MapMode.READ_WRITE, 0, 2 * 1024 * 1024 * 1024 - 1);
mappedByteBuffers[1] = channel.map(FileChannel.MapMode.READ_WRITE, 0, 2 * 1024 * 1024 * 1024 - 1);
mappedByteBuffers[2] = channel.map(FileChannel.MapMode.READ_WRITE, 0, 2 * 1024 * 1024 * 1024 - 1);
mappedByteBuffers[3] = channel.map(FileChannel.MapMode.READ_WRITE, 0, 2 * 1024 * 1024 * 1024 - 1);
mappedByteBuffers[4] = channel.map(FileChannel.MapMode.READ_WRITE, 0, 2 * 1024 * 1024 * 1024 - 1); for (int j = 0; j < 2*1024*1024*1024 - 1; j++) {
mappedByteBuffers[0].put("a".getBytes());
}
TimeUnit.SECONDS.sleep(1);
byte []to = new byte[1]; for (int j = 0; j < 2*1024*1024*1024 - 1; j++) {
mappedByteBuffers[1].get(to);
mappedByteBuffers[2].get(to);
mappedByteBuffers[3].get(to);
mappedByteBuffers[4].get(to);
} while(true) {
TimeUnit.SECONDS.sleep(1);
}
}

等到程序运行到最后的死循环的时候,我们来看top -c的结果:

KiB Mem :  7493092 total,   147876 free,  3891680 used,  3453536 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 2845100 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+
25458 zhangha+ 20 0 14.147g 8.840g 8.599g S 0.0 124 2:33.16 java

可以观察到非常有意思的现象,这个进程占用了124%的内存,实际上Swap为0。总占用也没到100%。这是为什么呢?

我们来看下这个进程的smaps文件,这里进程号是25485,我们映射的文件是FileMmapTest.txt:

$ grep -A 11 FileMmapTest.txt  /proc/25458/smaps
7fa870000000-7fa8f0000000 rw-s 00000000 ca:01 25190272 /home/zhanghaoxin/FileMmapTest.txt
Size: 2097152 kB
Rss: 2097152 kB
Pss: 493463 kB
Shared_Clean: 2097152 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 0 kB
Referenced: 2014104 kB
Anonymous: 0 kB
AnonHugePages: 0 kB
Swap: 0 kB
--
7fa8f0000000-7fa970000000 rw-s 00000000 ca:01 25190272 /home/zhanghaoxin/FileMmapTest.txt
Size: 2097152 kB
Rss: 2097152 kB
Pss: 493463 kB
Shared_Clean: 2097152 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 0 kB
Referenced: 2014104 kB
Anonymous: 0 kB
AnonHugePages: 0 kB
Swap: 0 kB
--
7fa970000000-7fa9f0000000 rw-s 00000000 ca:01 25190272 /home/zhanghaoxin/FileMmapTest.txt
Size: 2097152 kB
Rss: 2097152 kB
Pss: 493463 kB
Shared_Clean: 2097152 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 0 kB
Referenced: 2014104 kB
Anonymous: 0 kB
AnonHugePages: 0 kB
Swap: 0 kB
--
7fa9f0000000-7faa70000000 rw-s 00000000 ca:01 25190272 /home/zhanghaoxin/FileMmapTest.txt
Size: 2097152 kB
Rss: 2097152 kB
Pss: 493463 kB
Shared_Clean: 2097152 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 0 kB
Referenced: 2014104 kB
Anonymous: 0 kB
AnonHugePages: 0 kB
Swap: 0 kB
--
7faa70000000-7faaf0000000 rw-s 00000000 ca:01 25190272 /home/zhanghaoxin/FileMmapTest.txt
Size: 2097152 kB
Rss: 616496 kB
Pss: 123299 kB
Shared_Clean: 616496 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 0 kB
Referenced: 616492 kB
Anonymous: 0 kB
AnonHugePages: 0 kB
Swap: 0 kB

其中比较重要的8个字段的含义分别如下:

  • Size:表示该映射区域在虚拟内存空间中的大小。
  • Rss:表示该映射区域当前在物理内存中占用了多少空间 
  • Pss:该虚拟内存区域平摊计算后使用的物理内存大小(有些内存会和其他进程共享,例如mmap进来的)。比如该区域所映射的物理内存部分同时也被另一个进程映射了,且该部分物理内存的大小为1000KB,那么该进程分摊其中一半的内存,即Pss=500KB。
  • Shared_Clean:和其他进程共享的未被改写的page的大小
  • Shared_Dirty: 和其他进程共享的被改写的page的大小
  • Private_Clean:未被改写的私有页面的大小。
  • Private_Dirty: 已被改写的私有页面的大小。
  • Swap:表示非mmap内存(也叫anonymous memory,比如malloc动态分配出来的内存)由于物理内存不足被swap到交换空间的大小。

我们可以看到,把这五个MappedByteBuffer的Pss加起来正好是2097151,就是我们映射的大小。可以推断出,我们这五个MappedByteBuffer在linux中的实现就是对应同一块内存。

同时,top命令看到的内存并不准,top,命令统计的是RSS字段,其实对于MMAP来说,更准确的应该是统计PSS字段

微信搜索“我的编程喵”关注公众号,每日一刷,轻松提升技术,斩获各种offer

2021-2-25:对于 Java MMAP,如何查看文件映射脏页,如何统计MMAP的内存大小?的更多相关文章

  1. mmap和普通文件读写的区别和比较 & mmap的注意点

    参考 http://www.cnblogs.com/huxiao-tee/p/4660352.html 对linux文件系统不了解的朋友,请参阅我之前写的博文<从内核文件系统看文件读写过程> ...

  2. linux查看文件夹大小,备份文件夹zip压缩解压

    linux查看文件夹大小,备份文件夹zip压缩解压 du -sh : 查看当前目录总共占的容量.而不单独列出各子项占用的容量 du -lh --max-depth=1 : 查看当前目录下一级子文件和子 ...

  3. Java使用RandomAccessFile读写文件

    目录 转载自:http://blog.csdn.net/akon_vm/article/details/7429245 Java RandomAccessFile RandomAccessFile是用 ...

  4. Java网络编程和NIO详解8:浅析mmap和Direct Buffer

    Java网络编程与NIO详解8:浅析mmap和Direct Buffer 本系列文章首发于我的个人博客:https://h2pl.github.io/ 欢迎阅览我的CSDN专栏:Java网络编程和NI ...

  5. Java网络编程与NIO详解8:浅析mmap和Direct Buffer

    微信公众号[黄小斜]作者是蚂蚁金服 JAVA 工程师,目前在蚂蚁财富负责后端开发工作,专注于 JAVA 后端技术栈,同时也懂点投资理财,坚持学习和写作,用大厂程序员的视角解读技术与互联网,我的世界里不 ...

  6. 25个Java机器学习工具和库

    本列表总结了25个Java机器学习工具&库: 1. Weka集成了数据挖掘工作的机器学习算法.这些算法可以直接应用于一个数据集上或者你可以自己编写代码来调用.Weka包括一系列的工具,如数据预 ...

  7. Java-Runoob-高级教程-实例-环境设置实例:4.Java 实例 – 如何查看当前 Java 运行的版本?

    ylbtech-Java-Runoob-高级教程-实例-环境设置实例:4.Java 实例 – 如何查看当前 Java 运行的版本? 1.返回顶部 1. Java 实例 - 如何查看当前 Java 运行 ...

  8. 25个Java机器学习工具&库--转载

    本列表总结了25个Java机器学习工具&库: 1. Weka集成了数据挖掘工作的机器学习算法.这些算法可以直接应用于一个数据集上或者你可以自己编写代码来调用.Weka包括一系列的工具,如数据预 ...

  9. 转:25个Java机器学习工具和库

    转自:http://www.cnblogs.com/data2value/p/5419864.html 本列表总结了25个Java机器学习工具&库: 1. Weka集成了数据挖掘工作的机器学习 ...

随机推荐

  1. Linux 配置永久辅助IP

    1.什么是辅助IP 辅助IP来源于Linux之中,Linux的系统网卡可以支持多IP的绑定,而辅助IP多用于解耦解决服务之间的兼容性问题,常见的应用场景有: 虚拟IP,高可用飘逸: 永久临时IP解耦使 ...

  2. Java帝国的成立

    java帝国的成立 一场旷日持久的战争 1972年C语言诞生 贴近硬件 ,运行极快 , 效率极低 操作系统, 编译器 ,数据库, 网络系统 指针和内存 (容易犯错 , 暴力) 1982 年C++诞生 ...

  3. Flink-v1.12官方网站翻译-P005-Learn Flink: Hands-on Training

    学习Flink:实践培训 本次培训的目标和范围 本培训介绍了Apache Flink,包括足够的内容让你开始编写可扩展的流式ETL,分析和事件驱动的应用程序,同时省略了很多(最终重要的)细节.本书的重 ...

  4. Malaysia Trip Memory ('-ωก)

    独白 ​ 初次见面,睡意阑珊.日轮.稀疏.惨白色.墨绿色,\(\rho_{atm}>\rho_{space}\) 的作用被赤道所隐藏,一时的不知所从,斑斓成了单一.之后的故事,踏上一辆盛装打扮的 ...

  5. Pytest(15)pytest分布式执行用例

    前言 平常我们功能测试用例非常多时,比如有1千条用例,假设每个用例执行需要1分钟,如果单个测试人员执行需要1000分钟才能跑完 当项目非常紧急时,会需要协调多个测试资源来把任务分成两部分,于是执行时间 ...

  6. mitmproxy使用详解

    mitmproxy 相比Charles.fiddler的优点在于,它可以命令行方式或脚本的方式进行mock mitmproxy不仅可以像Charles那样抓包,还可以对请求数据进行二次开发,进入高度二 ...

  7. codeforces 128B. String

    time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standa ...

  8. hdu4325 Flowers

    Problem Description As is known to all, the blooming time and duration varies between different kind ...

  9. 二维码 : QRcode

    1 1 1 ★什么是二维码 通俗解释: 二维码是一种能存储信息的特定格式图片. 技术解释: 二维码(2-dimensional bar code) ,又称二维条码, 是用某种特定的几何图形按一定规律在 ...

  10. JavaScript interview Question - Create a Array with two papameters without using loop!

    JavaScript interview Question - Create a Array with two papameters without using loop! JavaScript - ...