一、 进程内存统计

cat /proc/[pid]/status

通过/proc/[pid]/status可以查看进程的内存使用情况,包括虚拟内存大小(VmSize),物理内存大小(VmRSS),数据段大小(VmData),栈的大小(VmStk),代码段的大小(VmExe),共享库的代码段大小(VmLib)等等。

* Name: java /*进程的程序名*/

* State: S (sleeping) /*进程的状态信息,具体参见*/

* Tgid: 9744 /*线程组号*/

* Pid: 9744 /*进程pid*/

* PPid: 7672 /*父进程的pid*/

* TracerPid: 0 /*跟踪进程的pid*/

* VmPeak: 60184 kB /*进程地址空间的大小*/

* VmSize: 60180 kB /*进程虚拟地址空间的大小reserved_vm:进程在预留或特殊的内存间的物理页*/

* VmLck: 0 kB /*进程已经锁住的物理内存的大小.锁住的物理内存不能交换到硬盘*/

* VmHWM: 18020 kB /*文件内存映射和匿名内存映射的大小*/

* VmRSS: 18020 kB /*应用程序正在使用的物理内存的大小,就是用ps命令的参数rss的值 (rss)*/

* VmData: 12240 kB /*程序数据段的大小(所占虚拟内存的大小),存放初始化了的数据*/

* VmStk: 84 kB /*进程在用户态的栈的大小*/

* VmExe: 576 kB /*程序所拥有的可执行虚拟内存的大小,代码段,不包括任务使用的库 */

* VmLib: 21072 kB /*被映像到任务的虚拟内存空间的库的大小*/

* VmPTE: 56 kB /*该进程的所有页表的大小*/

* Threads: 1 /*共享使用该信号描述符的任务的个数*/

二、JVM 内存分配

java内存组成介绍:堆(Heap)和非堆(Non-heap)内存

按照官方的说法:“Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配。堆是在 Java 虚拟机启动时创建的。” “在JVM中堆之外的内存称为非堆内存(Non-heap memory)”。

可以看出JVM主要管理两种类型的内存:堆和非堆。

简单来说堆就是Java代码可及的内存,是留给开发人员使用的;非堆就是JVM留给自己用的。

所以方法区、JVM内部处理或优化所需的内存(如JIT编译后的代码缓存)、每个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法 的代码都在非堆内存中。

1.JVM 本身需要的内存,包括其加载的第三方库以及这些库分配的内存

2.NIO 的 DirectBuffer 是分配的 native memory

3.内存映射文件,包括 JVM 加载的一些 JAR 和第三方库,以及程序内部用到的。上面 pmap 输出的内容里,有一些静态文件所占用的大小不在 Java 的 heap 里,因此作为一个Web服务器,赶紧把静态文件从这个Web服务器中人移开吧,放到nginx或者CDN里去吧。

4.JIT, JVM会将Class编译成native代码,这些内存也不会少,如果使用了Spring的AOP,CGLIB会生成更多的类,JIT的内存开销也会随之变大,而且Class本身JVM的GC会将其放到Perm Generation里去,很难被回收掉,面对这种情况,应该让JVM使用ConcurrentMarkSweep GC,并启用这个GC的相关参数允许将不使用的class从Perm Generation中移除, 参数配置:-XX:+UseConcMarkSweepGC -X:+CMSPermGenSweepingEnabled -X:+CMSClassUnloadingEnabled,如果不需要移除而Perm Generation空间不够,可以加大一点:-X:PermSize=256M -X:MaxPermSize=512M

5.JNI,一些JNI接口调用的native库也会分配一些内存,如果遇到JNI库的内存泄露,可以使用valgrind等内存泄露工具来检测

6.线程栈,每个线程都会有自己的栈空间,如果线程一多,这个的开销就很明显了

7.jmap/jstack 采样,频繁的采样也会增加内存占用,如果你有服务器健康监控,记得这个频率别太高,否则健康监控变成致病监控了。

1. 方法区

也称”永久代” 、“非堆”,它用于存储虚拟机加载的类信息、常量、静态变量、是各个线程共享的内存区域。默认最小值为 16 MB,最大值为 64 MB,可以通过-XX: PermSize 和 -XX: MaxPermSize 参数限制方法区的大小。

运行时常量池:是方法区的一部分,Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译器生成的各种符号引用,这部分内容将在类加载后放到方法区的运行时常量池中。

2. 虚拟机栈

描述的是java 方法执行的内存模型:每个方法被执行的时候 都会创建一个“栈帧”用于存储局部变量表(包括参数)、操作栈、方法出口等信息。

每个方法被调用到执行完的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。声明周期与线程相同,是线程私有的。

局部变量表存放了编译器可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(引用指针,并非对象本身),其中64位长度的long和double类型的数据会占用2个局部变量的空间,其余数据类型只占1个。

局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在栈帧中分配多大的局部变量是完全确定的,在运行期间栈帧不会改变局部变量表的大小空间。

3. 本地方法栈

与虚拟机栈基本类似,区别在于虚拟机栈为虚拟机执行的java方法服务,而本地方法栈则是为Native方法服务。

4. 堆

也叫做java 堆、GC堆是java虚拟机所管理的内存中最大的一块内存区域,也是被各个线程共享的内存区域,在JVM启动时创建。

该内存区域存放了对象实例及数组(所有 new 的对象)。其大小通过 -Xms (最小值) 和 -Xmx (最大值) 参数设置,-Xms为 JVM 启动时申请的最小内存,默认为操作系统物理内存的 1/64 但小于 1G;

-Xmx 为 JVM 可申请的最大内存,默认为物理内存的1/4但小于 1G,默认当空余堆内存小于 40% 时,JVM 会增大 Heap 到 -Xmx 指定的大小,可通过 -XX:MinHeapFreeRation= 来指定这个比列;

当空余堆内存大于70%时,JVM 会减小 heap 的大小到 -Xms 指定的大小,可通过XX:MaxHeapFreeRation= 来指定这个比列,对于运行系统,为避免在运行时频繁调整 Heap 的大小,通常 -Xms 与 -Xmx 的值设成一样。

由于现在收集器都是采用分代收集算法,堆被划分为新生代和老年代。新生代主要存储新创建的对象和尚未进入老年代的对象。老年代存储经过多次新生代GC(Minor GC)任然存活的对象。

5. 程序计数器

是最小的一块内存区域,它的作用是当前线程所执行的字节码的行号指示器,在虚拟机的模型里,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、异常处理、线程恢复等基础功能都需要依赖计数器完成。

三、直接内存

直接内存并不是虚拟机内存的一部分,也不是Java虚拟机规范中定义的内存区域。jdk1.4中新加入的NIO,引入了通道与缓冲区的IO方式,它可以调用Native方法直接分配堆外内存,这个堆外内存就是本机内存,不会影响到堆内存的大小。

四、JVM 内存分析

1. 查看 JVM 堆内存情况

[root@server ~]$ jmap -heap 837

Attaching to process ID 837, please wait...

Debugger attached successfully.

Server compiler detected.

JVM version is 24.71-b01

using thread-local object allocation.

Parallel GC with 4 thread(s)//GC 方式

Heap Configuration: //堆内存初始化配置

MinHeapFreeRatio = 0 //对应jvm启动参数-XX:MinHeapFreeRatio设置JVM堆最小空闲比率(default 40)

MaxHeapFreeRatio = 100 //对应jvm启动参数 -XX:MaxHeapFreeRatio设置JVM堆最大空闲比率(default 70)

MaxHeapSize      = 2082471936 (1986.0MB) //对应jvm启动参数-XX:MaxHeapSize=设置JVM堆的最大大小

NewSize          = 1310720 (1.25MB)//对应jvm启动参数-XX:NewSize=设置JVM堆的‘新生代’的默认大小

MaxNewSize      = 17592186044415    MB//对应jvm启动参数-XX:MaxNewSize=设置JVM堆的‘新生代’的最大大小

OldSize          = 5439488 (5.1875MB)//对应jvm启动参数-XX:OldSize=:设置JVM堆的‘老生代’的大小

NewRatio        = 2 //对应jvm启动参数-XX:NewRatio=:‘新生代’和‘老生代’的大小比率

SurvivorRatio    = 8 //对应jvm启动参数-XX:SurvivorRatio=设置年轻代中Eden区与Survivor区的大小比值

PermSize        = 21757952 (20.75MB)  //对应jvm启动参数-XX:PermSize=:设置JVM堆的‘永生代’的初始大小

MaxPermSize      = 85983232 (82.0MB)//对应jvm启动参数-XX:MaxPermSize=:设置JVM堆的‘永生代’的最大大小

G1HeapRegionSize = 0 (0.0MB)

Heap Usage://堆内存使用情况

PS Young Generation

Eden Space://Eden区内存分布

capacity = 33030144 (31.5MB)//Eden区总容量

used    = 1524040 (1.4534378051757812MB)  //Eden区已使用

free    = 31506104 (30.04656219482422MB)  //Eden区剩余容量

4.614088270399305% used //Eden区使用比率

From Space:  //其中一个Survivor区的内存分布

capacity = 5242880 (5.0MB)

used    = 0 (0.0MB)

free    = 5242880 (5.0MB)

0.0% used

To Space:  //另一个Survivor区的内存分布

capacity = 5242880 (5.0MB)

used    = 0 (0.0MB)

free    = 5242880 (5.0MB)

0.0% used

PS Old Generation //当前的Old区内存分布

capacity = 86507520 (82.5MB)

used    = 0 (0.0MB)

free    = 86507520 (82.5MB)

0.0% used

PS Perm Generation//当前的 “永生代” 内存分布

capacity = 22020096 (21.0MB)

used    = 2496528 (2.3808746337890625MB)

free    = 19523568 (18.619125366210938MB)

11.337498256138392% used

670 interned Strings occupying 43720 bytes.

前面jmap输出的内容里,MaxHeapSize 是在命令行上配的,-Xmx4096m,这个java程序可以用到的最大堆内存。

VSZ是指已分配的线性空间大小,这个大小通常并不等于程序实际用到的内存大小,产生这个的可能性很多,比如内存映射,共享的动态库,或者向系统申请了更多的堆,都会扩展线性空间大小,要查看一个进程有哪些内存映射,可以使用 pmap 命令来查看:

pmap -x [pid]

[root@server ~]$ pmap -x 837

837:  java

Address          Kbytes    RSS  Dirty Mode  Mapping

0000000040000000      36      4      0 r-x--  java

0000000040108000      8      8      8 rwx--  java

00000000418c9000  13676  13676  13676 rwx--    [ anon ]

00000006fae00000  83968  83968  83968 rwx--    [ anon ]

0000000700000000  527168  451636  451636 rwx--    [ anon ]

00000007202d0000  127040      0      0 -----    [ anon ]

...

...

00007f55ee124000      4      4      0 r-xs-  az.png

00007fff017ff000      4      4      0 r-x--    [ anon ]

ffffffffff600000      4      0      0 r-x--    [ anon ]

----------------  ------  ------  ------

total kB        7796020 3037264 3023928

这里可以看到很多anon,这些表示这块内存是由mmap分配的。

RSZ是Resident Set Size,常驻内存大小,即进程实际占用的物理内存大小, 在现在这个例子当中,RSZ和实际堆内存占用差了2.3G,这2.3G的内存组成分别为:

查看 JVM 堆各个分区的内存情况

jstat -gcutil [pid]

[root@server ~]$ jstat -gcutil 837 1000 20

S0    S1    E      O      P    YGC    YGCT    FGC    FGCT    GCT

0.00  80.43  24.62  87.44  98.29  7101  119.652    40  19.719  139.371

0.00  80.43  33.14  87.44  98.29  7101  119.652    40  19.719  139.371

分析 JVM 堆内存中的对象

查看存活的对象统计

jmap -histo:live [pid]

dump 内存

jmap -dump:format=b,file=heapDump [pid]

然后用jhat命令可以参看

jhat -port 5000 heapDump

在浏览器中访问:http://localhost:5000/ 查看详细信息

linux进程的内存空间,Linux进程内存统计相关推荐

  1. mpu 配置内存空间_PCIE的内存地址空间、I/O地址空间和配置地址空间

    pci设备与其它接口的设备(如i2c设备)最大的不同是存在内存地址空间和配置地址空间 首先区分一下IO空间和内存空间 cpu会访问的设备一般有内存和外设寄存器,如下图所示.x86架构采用独立编址将内存 ...

  2. PCIe to AXI Translation——PCIe 内存空间到AXI内存空间的转换

    PCIe to AXI Translation--PCIe 内存空间到AXI内存空间的转换 UltraScale系列芯片包含PCIe的Gen3 Integrated Block IP核在内的多种不同功 ...

  3. linux创建新进程就分配空间,linux几种创建进程的方法

    在Linux中主要提供了fork.vfork.clone三个进程创建方法. 在linux源码中这三个调用的执行过程是执行fork(),vfork(),clone()时,通过一个系统调用表映射到sys_ ...

  4. pcie读写ddr_一文详解PCIe内存空间到AXI内存空间的转换

    UltraScale系列芯片包含PCIe的Gen3 Integrated Block IP核在内的多种不同功能的IP核都会有一页设置为PCIe:BARs,设置IP核的Base address regi ...

  5. 如何在linux下创建表空间,linux下创建oracle表空间

    来自:http://blog.sina.com.cn/s/blog_62192aed01018aep.html 1 . 登录服务器 2 . 查看磁盘空间是否够大df -h -h更具目前磁盘空间和使用情 ...

  6. alloc_page分配内存空间--Linux内存管理(十七)

    1 前景回顾 在内核初始化完成之后, 内存管理的责任就由伙伴系统来承担. 伙伴系统基于一种相对简单然而令人吃惊的强大算法. Linux内核使用二进制伙伴算法来管理和分配物理内存页面, 该算法由Know ...

  7. linux 文件系统 簇 浪费空间,Linux rm -rf删除文件不释放空间的解决办法

    前几天发现在Linux系统下有一个很大的无用文件,于是用rm -rf 删除,然后用df -h查看磁盘空间,发现即使文件被删除了,但文件所占用的空间并未释放,十分疑惑,于是在网上找到了解决方案,即使用l ...

  8. 在linux看数据库表空间,Linux平台达梦数据库V7之表空间管理

    表空间如果发生损坏(表空间还原失败,或者数据文件丢失或损坏)的情况下,允许将表空间切换为 CORRUPT 状态,并删除损坏的表空间,如果表空间上定义有对象,需要先将所有对象删除,再删除表空间. 2.4 ...

  9. linux增加电子档案空间,Linux 建立 SWAP 档案空间

    Swap 档案跟 Swap 分割区差不多, 分别是 Swap 档案是用档案的方式建立, 不是使用独立硬盘分割区. 以下是在 Linux 下建立 Swap 档案的方法. 建立 swap 档案是使用 bl ...

最新文章

  1. MyBatis框架学习 DAY_02:使用XML配置文件/多参数问题 / FOREACH /IF / #{}和${} / 创建SSM框架流程
  2. GDB中应该知道的几个调试方法
  3. 从上往下 流式布局_揭秘做好网站结构优化的4步(下)
  4. ML之DT:基于简单回归问题训练决策树(DIY数据集+七种{1~7}深度的决策树{依次进行10交叉验证})
  5. python获取数组中大于某一阈值的那些索引值_使用Python+OpenCV进行实时车道检测...
  6. IClass与电源管理
  7. 九年级数学解方程50道_初中数学公式中考知识点总结,初三数学上册,九年级数学上册...
  8. 他回国后对学生说,玩会这12个游戏就能掌握python基础,其实不难
  9. 为什么说只有深度思考才能让你持续赚到钱?
  10. pointofix 全局快捷键_屏幕画笔(Pointofix)
  11. 樊昌信通信原理第7版笔记和课后习题答案
  12. 11部委印发《智能汽车创新发展战略》,加快智能汽车应用北斗高精度时空基准服务
  13. 智慧环境应急平台建设方案
  14. 企业个人所得税网上申报系统_增值税、企业所得税、个人所得税申报难点梳理...
  15. 深度学习在视频动作识别应用
  16. php 获取当前的域名
  17. python中in是什么意思中文_python中的in是什么意思
  18. Firefox火狐浏览器主页被360篡改了
  19. 不用工具,如何快速计算文件的MD5?
  20. Python挑战游戏( PythonChallenge)闯关之路Level 0

热门文章

  1. RC4加密算法初次接触以及深入学习
  2. 新房装修步骤及注意事项,让您有准备的装修步骤
  3. 2019最全学习路线
  4. Tbox 相关名词总结
  5. 基于Docker搭建hdfs分布式实验环境
  6. c# winform登录窗口按enter自动登录设置
  7. 关于:自动代理 pac 文件示例
  8. Android 安装apk时,报错 Failure [INSTALL_FAILED_TEST_ONLY]
  9. tomcat部署方式
  10. 实习闲余——对Vue整理和总结