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原生工具更好用

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值