内存又称主存,是 CPU 能直接寻址的存储空间(由半导体器件制成)。内存的特点是存取速率快,断电一般不保存数据(非持久化设备),和寄存器类似。内存的作用是用于暂时存放 CPU 中的运算数据,以及与硬盘等外部存储器交换的数据,可保障 CPU 计算的稳定性和高性能。内存就像人的神经系统,负责传递数据,产生命令的交互作用。
常见的内存问题
当系统资源在错误使用的情况下,可能导致使用完毕的资源无法回收或者没有回收,这个时候出现的问题叫内存泄漏;内存泄漏可能使得内存使用率持续保持在较高水位,此时一旦出现大内存的占用就很容易出现内存溢出
1.内存泄漏(Memory Leak)
内存泄漏是指程序在申请内存后,无法释放已申请的内存空间,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出。
内存泄漏按发生方式分为常发性内存泄漏,偶发性内存泄漏,一次性内存泄漏,隐式内存泄漏,四种,前两种不用说明。一次性内存泄漏,指的是发生内存泄漏的代码只会被执行一次,比如,在类的构造函数中分配内存,在析构函数中却没有释放该内存,所以内存泄漏只会发生一次。 隐式内存泄漏,指的是程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。这看起来没啥问题,但是一般情况下,一个系统一次运行就是好几个月甚至更久,这样内存长时间堆积,不释放,就会导致内存溢出。
2.内存溢出(out of memory)
内存溢出,是性能测试中常见的问题。即OOM。是指程序申请内存时,没有足够的内存供申请者使用。当内存的 available 较少时,此时一旦出现大内存的占用就有可能导致内存溢出,甚至触发系统的 OOM Killer 直接终止进程。
通过dmesg -T 命令,可以查看系统有没有进行OOM Killer操作。
内存分析步骤
1.用 free -h查看系统内存的使用情况
free命令结果说明
-
total
:物理内存的总大小 -
used
:被使用的物理内存大小 -
free
:系统未使用的物理内存总量 -
shared
:共享内存,由于是多个进程间共享使用 -
buffer/cached
:磁盘缓存的大小 -
available
:从应用的角度看还可以被进程使用的物理内存大小。Linux 内核为了提升磁盘操作的性能,会消耗一部分内存去缓存磁盘数据,就是buffer
和cache
。当应用程序需要内存时,如果没有足够的free
内存可以用,内核就会从buffer
和cache
中回收内存来满足应用程序的请求。所以从应用程序的角度来说,available = free + buffer + cache
。请注意,这只是一个很理想的计算方式,实际中的数据往往有较大的误差。
2. 用 jstat -gcutil pid[进程ID] 查看 JVM 使用情况
命令结果说明:
-
S0
:幸存1区当前使用比例 -
S1
:幸存2区当前使用比例 -
E
:伊甸园区使用比例 -
O
:老年代使用比例 -
M
:元数据区使用比例 -
CCS
:压缩使用比例 -
YGC
:年轻代垃圾回收次数 -
FGC
:老年代垃圾回收次数 -
FGCT
:老年代垃圾回收消耗时间 -
GCT
:垃圾回收消耗总时间
连续打印jvm使用情况,当发现FGC(全盘垃圾回收)次数增多,但是o列(老年代)没有下降,或者越来越大时,说明存在内存泄漏导致内存已经无法回收。此时我们定位到问题出在内存,接下来就是要将内存 dump
下来进行进一步分析了。
3. dump 内存
手动执行 jmap -dump:format=b,file=path/fileName.hprof[导出路径] pid[进程ID] 命令可导出内存使用情况
也可以通过设置,当系统内存溢出时,自动导出内存信息。在jvm参数中设置-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heapdump/heapdump_$(date +%Y%m%d-%H%M).hprof
4.mat 分析内存
将导出的hprof文件导入到mat中进行分析,详细操作见百度