2.4-内存性能-内存泄露

2021/5/30 7:21:33

本文主要是介绍2.4-内存性能-内存泄露,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

目录

四、内存泄露

4.1 内存的分配和回收

4.1.1 内存段导致内存泄露

4.2 内存泄露的检测、定位及处理 —— vmstat/bcc

4.2.1 案例分析

4.2.2 检查内存泄露的工具 —— memleak

4.3 Java 项目内存泄露的监控

4.3.1 出现内存泄露的可能现象

4.4 总结


四、内存泄露

什么是内存泄露?

  • 没正确回收动态分配后的内存,导致内存泄漏
  • 访问的是已分配内存边界外的地址,导致程序异常退出

什么是内存溢出(OOM)?

  • 程序在申请内存时,没有足够的内存空间供其使用

4.1 内存的分配和回收

4.1.1 内存段导致内存泄露

用户空间内存包括不同的内存段(只读段、数据段、堆、栈以及文件映射段),这些内存段是应用程序使用内存的基本方式。

哪些内存段会导致内存泄漏?

  1. 只读段 —— 程序代码和常量
    1. 是只读,不会再去分配新的内存,因此不会产生内存泄露
  2. 数据段 —— 全局变量和静态变量
    1. 这些变量在定义时就已经确定了大小,因此不会产生内存泄露
  3. 堆 —— 由应用程序自己分配和管理
    1. 除非程序退出,堆内存不会被系统自动释放,而需要应用程序调用库函数free()来释放。如果没有释放堆内存,就会造成内存泄露。
    2. idc 环境 - jvm :
      1. jvm 自身存在一套堆信息的释放机制,在程序运行过程中,某些被使用的内存会被标记(由算法指定),标记完成后,通过jvm的回收机制进行释放。如果设定的jvm内存不够,将频繁出现GC,从而影响程序性能
  4. 栈 —— 由系统自动分配和管理
    1. 一旦程序运行超出了变量(例如整型 int)的作用域,栈内存就会被系统自动回收,就不会产生内存泄露的问题
  5. 文件映射段 —— 动态链接和共享内存
    1. 共享内存由程序动态分配和管理,如果程序在分配后忘了回收,就会导致跟堆内存类似的泄露为题

内存泄露危害

内存泄露危害很大,这些忘记释放的内存,不仅应用程序自己不能访问,系统也不能把他们再次分配给其他应用。内存泄露不断累积,甚至会消耗尽系统内存。虽然系统可以通过 OOM 机制杀死进程,但进程在 OOM 之前,可能已经引发了一连串的反应,导致严重的性能问题。

4.2 内存泄露的检测、定位及处理 —— vmstat/bcc

  • vmstat —— 观察内存的变化情况
  • bcc —— Linux 性能分析工具,用来动态追踪进程和内核行为

4.2.1 案例分析

安装后的工具路径:

/usr/share/bcc/tools

# install sysstat docker
sudo apt-get install -y sysstat docker.io
 
# Install bcc
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 4052245BD4284CDD
echo "deb https://repo.iovisor.org/apt/bionic bionic main" | sudo tee /etc/apt/sources.list.d/iovisor.list
sudo apt-get update
sudo apt-get install -y bcc-tools libbcc-examples linux-headers-$(uname -r)

4.2.2 检查内存泄露的工具 —— memleak

memleak 可以跟踪系统或指定进程的内存分配、释放请求,然后定期输出一个未释放内存和相应调用栈的汇总情况(默认5秒)

# -a 表示显示每个内存分配请求的大小以及地址
# -p 指定案例应用的 PID 号
$ /usr/share/bcc/tools/memleak -a -p $(pidof app)

4.3 Java 项目内存泄露的监控

#查看java进程的堆的配置信息,各区的空间大小和配置信息
jmap -heap pid
jmap -histo pid | head -20

#监控jvm的GC(垃圾回收情况)
jstat -gcutil pid 1000 100
//后面两个数字表示1000毫秒时间刷新一次 一共刷新100次
#图形界面
Jconsole
Jvisualvm

4.3.1 出现内存泄露的可能现象

  1. tps(每秒处理的事物数)曲线出现大幅度波动,趋势并且慢慢降低,甚至到0
  2. jstat -gcutil pid 1000 100 中,old(0)显示不断增加,FGC频繁发生变动,FGCT数值不断增加
  3. 通过jconsole/jvisualvm堆内存曲线不断上升,严重的接近内存曲线
  4. 定位 - dump文件
#java_dump文件
jmap -dump:live,format=b,file=xxx pid
#java_dump文件
jmap -dump:live,format=b,file=xxx pid
#java堆栈日志
jstack -l <pid> >> dump.log

4.4 总结

  • 应用程序可以访问的用户内存空间,由只读段、数据段、堆、栈以及文件映射等组成。
    • 堆内存和内存映射,需要应用程序来动态管理内存段
    • 标准库函数 malloc()来动态分配内存
    • 用完内存后,调用库函数_free()来释放
  • 完成开发任务后,用memleak工具,检查应用程序的运行中,内存是否泄漏。如果存在内存泄漏情况,再根据memleak输出的应用程序调用栈,定位内存的分配位置,从而释放不在访问的内存。
  • java看到的是jvm堆栈,用jmap等java原生工具更好用

 



这篇关于2.4-内存性能-内存泄露的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程