2.4-内存性能-内存泄露
作者:互联网
目录
4.2 内存泄露的检测、定位及处理 —— vmstat/bcc
四、内存泄露
什么是内存泄露?
- 没正确回收动态分配后的内存,导致内存泄漏
- 访问的是已分配内存边界外的地址,导致程序异常退出
什么是内存溢出(OOM)?
- 程序在申请内存时,没有足够的内存空间供其使用
4.1 内存的分配和回收
4.1.1 内存段导致内存泄露
用户空间内存包括不同的内存段(只读段、数据段、堆、栈以及文件映射段),这些内存段是应用程序使用内存的基本方式。
哪些内存段会导致内存泄漏?
- 只读段 —— 程序代码和常量
- 是只读,不会再去分配新的内存,因此不会产生内存泄露
- 数据段 —— 全局变量和静态变量
- 这些变量在定义时就已经确定了大小,因此不会产生内存泄露
- 堆 —— 由应用程序自己分配和管理
- 除非程序退出,堆内存不会被系统自动释放,而需要应用程序调用库函数free()来释放。如果没有释放堆内存,就会造成内存泄露。
- idc 环境 - jvm :
- jvm 自身存在一套堆信息的释放机制,在程序运行过程中,某些被使用的内存会被标记(由算法指定),标记完成后,通过jvm的回收机制进行释放。如果设定的jvm内存不够,将频繁出现GC,从而影响程序性能
- 栈 —— 由系统自动分配和管理
- 一旦程序运行超出了变量(例如整型 int)的作用域,栈内存就会被系统自动回收,就不会产生内存泄露的问题
- 文件映射段 —— 动态链接和共享内存
- 共享内存由程序动态分配和管理,如果程序在分配后忘了回收,就会导致跟堆内存类似的泄露为题
内存泄露危害
内存泄露危害很大,这些忘记释放的内存,不仅应用程序自己不能访问,系统也不能把他们再次分配给其他应用。内存泄露不断累积,甚至会消耗尽系统内存。虽然系统可以通过 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 出现内存泄露的可能现象
- tps(每秒处理的事物数)曲线出现大幅度波动,趋势并且慢慢降低,甚至到0
- jstat -gcutil pid 1000 100 中,old(0)显示不断增加,FGC频繁发生变动,FGCT数值不断增加
- 通过jconsole/jvisualvm堆内存曲线不断上升,严重的接近内存曲线
- 定位 - 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原生工具更好用
标签:应用程序,bcc,apt,内存,jvm,泄露,2.4 来源: https://blog.csdn.net/Jackson_Baekhyun/article/details/117392708