对JVM内存的分析,第四章已有介绍,对JVM以外的内存消耗,最为值得关注的是SWAP的消耗以及物理内存的消耗,这两方面的消耗都可基于OS的命令来查看。

vmstat

在命令行中输入vmstat,输出信息和内存相关的主要是:

  • memory下
    • swpd
    • free
    • buff
    • cache
  • swap下
    • si
    • so
      参数 意义
      swpd 指虚拟内存中已使用的部分(kb)
      free 指空闲物理内存
      cache 表示用于缓存的内存
      swap下的si 指每秒从disk读至内存的数据量
      swap下的so 指每秒从内存写入disk的数据量

swpd过高通常是物理内存不够用,os将物理内存中的一部分数据转为放入硬盘上进行存储,以腾出足够的空间供程序使用。

在目前运行的程序变化后,即从硬盘重新读取到内存中,以便恢复程序的运行,这个过程会产生swap IO,因此查看swap消耗情况主要关注的就是swap IO的状况

对于JAVA应用,属于单进程应用,因此只要JVM不是设置的过大,不会操作到swap区域。物理内存消耗过多,可能是

  • JVM设置过大
  • 创建的JAVA线程太多
  • 通过Direct ByteBuffer往物理内存中放置了过多的对象导致
  • 弱点
    • 不能分析进程所占用的内存量

sar

通过

1
sar -r

可以查看内存消耗的状况

demo

1
sar -r 2 5

image.png

参数 意义
kbswpfree swap空闲的大小
kbswpused swap已使用的大小
%swpused swap使用空间比例

linux会使用一些物理内存用于,buffer、cache,提升系统运行效率,可以认为可用的物理内存为:kbmemfree + kbbuffers + kbcached

  • 优点
    • 可以查询历史状况,以更加准确的分析趋势状况,例如:
1
sar –r –f /tmp/log/sa/sa12
  • 弱点
    • 不能分析进程所占用的内存量

top

通过 top 可查看进程所消耗的内存量,不过top看到的java进程的消耗内存是包括:

JVM 已分配的内存 + JAVA 应用所耗费的 JVM 以外的物理内存。

这会导致top中看到java进程消耗的内存大小可能超过

-Xmx + -XX:MaxPermSize

pidstat

pidstat –r –p [pid] [interval] [times]. 执行此命令可查看进程所占用的物理内存和虚拟内存的大小。

1
pid -r -p 2013 1 100

image.png

从以上几个工具来看,最合适找内存消耗分析的方法是:
结合top或pidstat以及jvm分析工具共同分析

总结

  • 如果内存消耗过高,一般指的是swap交换区的内存及物理内存使用过高(因为JVM最大能使用的内存是由-Xmx制定的)
    • 可先用vmstat,sar,top,pidstat等确认。要首先分析哪部分内存消耗高,JVM的还是之外的物理内存
      • 如果之外的,主要从线程数量以及Direct ByteBuffer的使用情况入手
      • 如果是JVM的,可结合JDK自带的工具或其他如jprofile,tda等分析。
    • 解决方法:及时释放对象,采用对象池,合理的缓存失效算法,考虑使用SoftReference以及WeakReference。