Linux和进程内存模型
一、Linux和进程内存模型
jvm是一个进程的身份运行在linux系统上,了解linux和进程的内存关系,是理解jvm和Linux内存关系的基础。
硬件、系统、进程三个层面的内存之间的概要关系
1、从硬件上看,linux系统有两部分组成:物理内存和SWAP(位于磁盘),物理内存是linux活动时使用的主要内存区域,当物理内存不够使用时,linux会把一部分暂时不用的内存数据放在SWAP中,以便腾出更多的可用内存空间;而当需要使用位于SWAP的数据时,必须先将其换回到内存中。
2、从linux系统上看,除了引导系统的BIN区,整个内存空间主要被分为两个部分:内核内存(Kernel space)、用户内存(user space)。
内核内存是linux自身使用的内存空间,主要提供给程序调度、内存分配、连接硬件资源等程序逻辑使用。用户内存是提供各个进程主要空间,Linux给各个进程提供相同的虚拟内存空间;这使的进程之间相互独立、互不干扰。实现的方法是采用虚拟内存技术:给每个进程分配一定的虚拟内存,如果虚拟内存使用完了,才分配物理内存,对于32的Linux系统来说,一般将0~3G的虚拟内存空间分配做为用户空间,将3~4G的虚拟内存空间分配为内核空间;64位系统的划分情况是类似的。
3、从进程的角度来看,进程能直接访问的用户内存(虚拟内存空间)被划分为5个部分:代码区、数据区、堆区、栈区、未使用区。
代码区主要存放应用程序的机器代码,运行过程中代码不能被修改,具有只读和固定大小的特点。
数据区存放了应用程序中的全局数据、静态数据和一些常量字符串等,该区大小也是固定的。
堆是运行时程序动态申请的空间,属于程序运行时直接申请、释放的内存资源。
栈区用来存放函数的传入参数、临时变量,以及返回地址等数据。
未使用区是分配新内存空间的预备区域。
二、进程和jvm内存模型
JVM本质就是一个进程,因此其内存模型也有进程的一般特点。但是,JVM又不是一个普通的进程,其在内存模型上有许多崭新的特点,主要原因有两个:1.JVM将许多本来属于操作系统管理范畴的东西,移植到了JVM内部,目的在于减少系统调用的次数;2. Java NIO,目的在于减少用于读写IO的系统调用的开销,JVM进程与普通进程内存模型比较如下图:
1、用户内存
上图特别强调了JVM进程模型的代码区和数据区指的是JVM自身的,而非Java程序的。普通进程栈区,在JVM一般仅仅用做线程栈。JVM的堆区和普通进程的差别是最大的,下面具体详细说明:
首先是永久代。永久代本质上是Java程序的代码区和数据区。Java程序中类(class),会被加载到整个区域的不同数据结构中去,包括常量池、域、方法数据、方法体、构造函数、以及类中的专用方法、实例初始化、接口初始化等。这个区域对于操作系统来说,是堆的一个部分;而对于Java程序来说,这是容纳程序本身及静态资源的空间,使得JVM能够解释执行Java程序。
其次是新生代和老年代。新生代和老年代才是Java程序真正使用的堆空间,主要用于内存对象的存储;但是其管理方式和普通进程有本质的区别。
普通进程在运行时给内存对象分配空间时,比如C++执行new操作时,会触发一次分配内存空间的系统调用,由操作系统的线程根据对象的大小分配好空间后返回;同时,程序释放对象时,比如C++执行delete操作时,也会触发一次系统调用,通知操作系统对象所占用的空间已经可以回收。
JVM对内存的使用和一般进程不同。JVM向操作系统申请一整段内存区域(具体大小可以在JVM参数调节)作为Java程序的堆(分为新生代和老年代);当Java程序申请内存空间,比如执行new操作,JVM将在这段空间中按所需大小分配给Java程序,并且Java程序不负责通知JVM何时可以释放这个对象的空间,垃圾对象内存空间的回收由JVM进行。
JVM的内存管理方式的优点是显而易见的,包括:第一,减少系统调用的次数,JVM在给Java程序分配内存空间时不需要操作系统干预,仅仅在Java堆大小变化时需要向操作系统申请内存或通知回收,而普通程序每次内存空间的分配回收都需要系统调用参与;第二,减少内存泄漏,普通程序没有(或者没有及时)通知操作系统内存空间的释放是内存泄漏的重要原因之一,而由JVM统一管理,可以避免程序员带来的内存泄漏问题。
最后是未使用区,未使用区是分配新内存空间的预备区域。对于普通进程来说,这个区域被可用于堆和栈空间的申请及释放,每次堆内存分配都会使用这个区域,因此大小变动频繁;对于JVM进程来说,调整堆大小及线程栈时会使用该区域,而堆大小一般较少调整,因此大小相对稳定。操作系统会动态调整这个区域的大小,并且这个区域通常并没有被分配实际的物理内存,只是允许进程在这个区域申请堆或栈空间。
2、内核内存
应用程序通常不直接和内核内存打交道,内核内存由操作系统进行管理和使用;不过随着Linux对性能的关注及改进,一些新的特性使得应用程序可以使用内核内存,或者是映射到内核空间。Java NIO正是在这种背景下诞生的,其充分利用了Linux系统的新特性,提升了Java程序的IO性能。
上图给出了Java NIO使用的内核内存在linux系统中的分布情况。nio buffer主要包括:nio使用各种channel时所使用的ByteBuffer、Java程序主动使用ByteBuffer.allocateDirector申请分配的Buffer。而在PageCache里面,nio使用的内存主要包括:FileChannel.map方式打开文件占用mapped、FileChannel.transferTo和FileChannel.transferFrom所需要的Cache(图中标示 nio file)。
通过JMX可以监控到NIO Buffer和 mapped 的使用情况,如下图所示。不过,FileChannel的实现是通过系统调用使用原生的PageCache,过程对于Java是透明的,无法监控到这部分内存的使用大小。
Linux和Java NIO在内核内存上开辟空间给程序使用,主要是减少不要的复制,以减少IO操作系统调用的开销。例如,将磁盘文件的数据发送网卡,使用普通方法和NIO时,数据流动比较下图所示:
将数据在内核内存和用户内存之间拷贝是比较消耗资源和时间的事情,而从上图我们可以看到,通过NIO的方式减少了2次内核内存和用户内存之间的数据拷贝。这是Java NIO高性能的重要机制之一(另一个是异步非阻塞)。
从上面可以看出,内核内存对于Java程序性能也非常重要,因此,在划分系统内存使用时候,一定要给内核留出一定可用空间。
Linux和进程内存模型的更多相关文章
- [转]Linux中进程内存与cgroup内存的统计
From: http://hustcat.github.io/about/ Linux中进程内存与cgroup内存的统计 在Linux内核,对于进程的内存使用与Cgroup的内存使用统计有一些相同和不 ...
- Linux的Application 内存模型---
Linux的内存模型,一般为: 现在的每个进程使用了全部4G线性空间.在加载程序时内核把程序加载到线性地址0x08048000开始的位置.这个位置当然>128MB.2G开始是共享库,3G开始是内 ...
- Linux查看进程内存占用及内存使用情况
LINUX进程内存占用查看方法(1)top可以直接使用top命令后,查看%MEM的内容.可以选择按进程查看或者按用户查看,如想查看oracle用户的进程内存使用情况的话可以使用如下的命令:$ top ...
- Linux C进程内存布局
当程序文件运行为进程时,进程在内存中获得空间.这个空间是进程自己的内存空间.每个进程空间按照如下方式分为不同区域: 进程内存空间布局图 text:代码段.存放的是程序的全部代码(指令),来源于二进制可 ...
- linux查看进程内存使用情况,以及将线程情况输出文件
用jmap把进程内存使用情况dump到文件中,再用jhat分析查看.jmap进行dump命令格式如下: jmap -dump:format=b,file=/tmp/dump.dat 21711 -- ...
- linux查看进程内存占用
ps -aux | grep xxx USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND 可以看到RSS ...
- Linux X86-64 进程内存空间布局
http://blog.csdn.net/woshinia/article/details/41722085 http://www.lenky.info/archives/2012/04/1424 h ...
- 深入理解java虚拟机(linux与jvm内存关系)
本文转载自美团技术团队发表的同名文章 https://tech.meituan.com/linux-jvm-memory.html 一, linux与进程内存模型 要理解jvm最重要的一点是要知道jv ...
- 探索 Linux 内存模型--转
引用:http://www.ibm.com/developerworks/cn/linux/l-memmod/index.html 理解 Linux 使用的内存模型是从更大程度上掌握 Linux 设计 ...
随机推荐
- TP5.0+小程序商城构建(1)
1.导语 1.整体的思路与编程思想(大局观.AOP面向切面编程,10-20%) 2.具体的编程知识与技巧(TP5.小程序.数据库等80%) 2.课程内容与产品技术点 1.ThinkPHP5框架 1.编 ...
- PMP认证考试的最新趋势及10大特征(针对改版后)
我们都知道,今年PMP认证考试的教材已经改版了,最新版的内容是有不少的改动的,我们在了解PMP考试的时候,也要了解PMP考试的最新趋势,以便拿出应对的方法. 一.情景题更接地气 虽然PMP考试中继续保 ...
- 解决plink报错:.bim file has a split chromosome. Use --make-bed by itself to remedy this.
由于plink1.9和1.07这两个版本互掐,经常出现各种不兼容问题,“.bim file has a split chromosome. Use --make-bed by itself to r ...
- 【译】7. Java反射——私有字段和私有方法
原文地址:http://tutorials.jenkov.com/java-reflection/private-fields-and-methods.html =================== ...
- Day7--Python--基础数据类型补充,集合,深浅拷贝
一.基础数据类型补充 1.join() 把列表中的每一项(必须是字符串)用字符串拼接 与split()相反 lst = ["汪峰", "吴君如", " ...
- postman基于webservice的请求
以 http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?op=getMobileCodeInfo 为例 1.先理解事例的内容,请求头和响应 ...
- id选择器为变量时
使用angularjs或者freemarker的同学基本都接触过一个问题:当使用list遍历数组值显示在页面,并要对所显示的数值进行操作时,如何选取数值所在标签? 以下是一个把地址id转为中文地址的函 ...
- Installation failed with message Failed to finalize session: INSTALL_FAILED_TEST_ONLY:installPackageLI.
这样还不行的话,加 -t吧.
- CentOS 6.x 最小化安装推荐安装的依赖包和修改内核参数
CentOS 6.x 最小化安装推荐安装的依赖包 我在日常工作中,新建的xenserver的虚拟机,CentOS release 6.9 (Final)操作系统,采用最小化安装,后续很多操作需要各种依 ...
- Struts2_参数获得方式
1.属性驱动 /** * @ClassName: Demo8Action * @Description: struts2如何获得参数 * 每次请求action时都会创建新的action实例对象 * @ ...