热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

java的Mmap二三事

先说些题外话,Java的内存管理一直是让人又爱又恨玩意。学生时代写Java程序主要考虑的只是实现算法、完成功能,偶尔碰到OutofMemory也是递归搞成死循环。什么垃圾回收、内存管理统统交给

    先说些题外话,Java的内存管理一直是让人又爱又恨玩意。学生时代写Java程序主要考虑的只是实现算法、完成功能,偶尔碰到OutofMemory也是递归搞成死循环。什么垃圾回收、内存管理统统交给JVM去烦恼。上班之后再用Java发现完全不是那么回事,大访问量的情况下如何减少fullgc和停顿时间,内存管理无法由程序员控制和干预、甚至无法获知究竟哪个部分用了多少内存有时着实让人有些抓狂。各位可能无法想象当我们撞大运般的用jdk6_u12代替之前的某个版本解决了困扰多时的内存在高峰期无法正常回收的问题(后面会提到)时,那种如释重负却又心有不甘的感觉。因为存在对于内存管理丝毫插不上手的无力感,从那时起,我就一直在寻找一种把数据丢到内存里但又能够对其有所控制的方法,mmap算是不错的选择。

    其实在日常工作中,很多时候最麻烦的问题是要把数据存在哪里和如何对这些数据进行存取和管理。保存数据也无外乎数据库、文件和内存这几种方式,我这里涉及到的情况是用户登陆时把很多数据(比如好友列表、在线信息等)从各个地方拉过来丢到内存里,当用户logout之后再把这些东西清理出去,其实就是一个临时的cache。目前的做法是弄几个HashMap,再起几个清理线程每隔一段时间遍历一遍把map里过期数据清理出去。看起来貌似没啥问题,事实上之前跑了很长时间也没出任何问题。但倒霉的是我接手不久之后,随着用户数量的增长,出现高峰期java进程占用内存数量越来越高、直到把所有内存都吃干净然后挂掉的现象。但是我用jprofiler等工具经过仔细分析验证之后发现即便是达到目前设计容量的上限,内存也还会有很大富余,那问题就出在JVM没有很好地进行内存回收。虽然升级JDK解决了问题,但是引发了我其他的一些思考。(1)对于内存管理引发的问题,如果jvm没帮我们搞定怎么办?虽然sun的更新还算快,我们也许不会每次都如此幸运(2)java对象占用的内存中远比我们通过看到的东西计算出来的要大很多,例如一个含有800万个key/value对的HashMap,其key和value都是int(注意不是Integer),在内存中大概就要340M。所以有些结构化数据,例如每个用户的年龄、性别、生日等信息(按ID进行索引)似乎用共享内存的方法开辟出一块缓冲区来管理更合适。(3)同样是这些信息,虽然只是临时的cache,但是我希望Server重启之后这些信息不要丢失,因为重新load需要不少时间和代价。     可能有不少人有这种需求,所以sun在jdk1.4里提供了共享内存和读盘文件进行映射的mmap方法,有了它上述问题几乎都可以得到解决,如果有更深层次的需要,比如数据格式定义和抽象、备份、扩容等需求的话也可以自己写代码进行扩展。写mmap的代码应该不难,这里就不去讨论了。这里我想关注一下别的问题,那就是我们知道unix/linux中的mmap是一种进程间通信的方式之一,所以多个进程map到同一个文件的话在内存中应该只有一份镜像数据。java的的底层实现也应该是这样,但是网上和一些书中只有在多线程情况下的讨论,没亲自验证过毕竟不太放心,所以我就想办法验证一下。这里值得一提的是,linux的ps、top等工具是没办法进行验证的,他们看到的都是程序的虚拟内存空间的大小[VIRT列],如果用同样的程序map同一个文件,那么看到的VIRT值是一样的。同理用more /proc/进程ID/maps也是一样:   可以看到两个进程map同一个文件之后所映射到的虚拟地址空间是一样的,但是用同样的程序换个同样大小的文件还是会映射到这个地址区间去,可见用这个方法是不可靠的。那么还是得用最原始的方法--写个程序验证一下。验证的原理是mmap既然是进程间通信的方式之一,那么如果一个进程先往里写而另一个进程读的话,那么读的的进程就应该能够读到写进程写入的信息,这样就能印证这个文件的映像在内存中只有一份copy了。我的程序如下: 程序的输出如下: 看样子,javammap没让我失望,确实是一个文件会map到内存相同的地址空间去,即该文件在内存中的映射只有一份。 PS:用/proc/进程ID/maps查看进程内存信息的时候还有点以外收获,当我用"java -cp . 主类名"这种什么都不加的方式启动一个应用程序的时候用TOP查看VIRT总是显示1G左右的大小,用/proc/进程ID/maps就可以比较清楚地看到可能是java虚拟机启动时候分配给应用程序的共享内存,可能是怕我们不够用吧^_^.
推荐阅读
  • 恶意软件分析的最佳编程语言及其应用
    本文介绍了学习恶意软件分析和逆向工程领域时最适合的编程语言,并重点讨论了Python的优点。Python是一种解释型、多用途的语言,具有可读性高、可快速开发、易于学习的特点。作者分享了在本地恶意软件分析中使用Python的经验,包括快速复制恶意软件组件以更好地理解其工作。此外,作者还提到了Python的跨平台优势,使得在不同操作系统上运行代码变得更加方便。 ... [详细]
  • 一次上线事故,30岁+的程序员踩坑经验之谈
    本文主要介绍了一位30岁+的程序员在一次上线事故中踩坑的经验之谈。文章提到了在双十一活动期间,作为一个在线医疗项目,他们进行了优惠折扣活动的升级改造。然而,在上线前的最后一天,由于大量数据请求,导致部分接口出现问题。作者通过部署两台opentsdb来解决问题,但读数据的opentsdb仍然经常假死。作者只能查询最近24小时的数据。这次事故给他带来了很多教训和经验。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • svnWebUI:一款现代化的svn服务端管理软件
    svnWebUI是一款图形化管理服务端Subversion的配置工具,适用于非程序员使用。它解决了svn用户和权限配置繁琐且不便的问题,提供了现代化的web界面,让svn服务端管理变得轻松。演示地址:http://svn.nginxwebui.cn:6060。 ... [详细]
  • Java和JavaScript是什么关系?java跟javaScript都是编程语言,只是java跟javaScript没有什么太大关系,一个是脚本语言(前端语言),一个是面向对象 ... [详细]
  • 本文介绍了5个基本Linux命令行工具的现代化替代品,包括du、top和ncdu。这些替代品在功能上进行了改进,提高了可用性,并且适用于现代化系统。其中,ncdu是du的替代品,它提供了与du类似的结果,但在一个基于curses的交互式界面中,重点关注占用磁盘空间较多的目录。 ... [详细]
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • 本文介绍了在Mac上搭建php环境后无法使用localhost连接mysql的问题,并通过将localhost替换为127.0.0.1或本机IP解决了该问题。文章解释了localhost和127.0.0.1的区别,指出了使用socket方式连接导致连接失败的原因。此外,还提供了相关链接供读者深入了解。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 本文介绍了Windows操作系统的版本及其特点,包括Windows 7系统的6个版本:Starter、Home Basic、Home Premium、Professional、Enterprise、Ultimate。Windows操作系统是微软公司研发的一套操作系统,具有人机操作性优异、支持的应用软件较多、对硬件支持良好等优点。Windows 7 Starter是功能最少的版本,缺乏Aero特效功能,没有64位支持,最初设计不能同时运行三个以上应用程序。 ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
  • 本文介绍了在CentOS 6.4系统中更新源地址的方法,包括备份现有源文件、下载163源、修改文件名、更新列表和系统,并提供了相应的命令。 ... [详细]
author-avatar
中二丶夜夜
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有