[转帖]记录一次spring-boot程序内存泄露排查
现象
spring boot项目jvm启动配置-Xms4g -Xmx4g,然而很不幸的是程序所占的内存越来越高,都达到了12个多G,只能临时重启服务
常用命令
jstat -class PIDjstat -compiler PIDjstat -gc PIDjstat -gccapacity PIDjstat -gcutil PID查看堆比例jstat -gccause PIDjstat -gcnew PIDjstat -gcnewcapacity PIDjstat -gcold PIDjstat -gcoldcapcacity PIDjstat -printcompilation PIDjmap -histo PID查看类的实例jmap -heap PID查看堆栈信息jmap -dump:live,format=b,file=/tmp/m.hprof PID保存内存的堆栈为文件jhat -J-Xmx2048m -port 5000 /tmp/m.hprof在线查看堆文件的类,速度比较慢jcmd PID GC.run强制gc
排查一:开发环境和测试环境调试
用jdk自带的jvisualvm.exe,查看最占空间的类和实例最多的类,找到其最近的内存释放点一般就是内存泄露对象,也可以用jmap查看jvm进程实例最多的类
- 本机启动程序,postman或者jmeter调用程序接口,可以直接直接用jvisualvm查看到堆栈信息
- 远程调试,在测试环境启用jmxremote,-Dcom.sun.management.jmxremote.port=10096 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false
但是堆栈信息只能先保存在测试服务器上,下载到本地后再用jvisualvm.exe打开
排查二:保存生成环境的内存进行分析
先用jmap命令将程序的内存数据保存下来,jmap -dump:live,format=b,file=m.hprof PID,其中PID是程序的进程号
/data/server/jdk/jdk1.8.0_171/bin/jmap -dump:live,format=b,file=/tmp/m.hprof 3478
- 将/tmp/m.hprof堆栈文件下载到本地电脑,用jvisualvm.exe打开分析,生产服务器外网太小,下载好慢
- 用mat分析,我是在一台空闲一点的生成服务器上使用,阿里云内网传输文件速度特别快,将下载的mat直接解压缩就可以使用了,因为文件太大内存不足所以需要修改 MemoryAnalyzer.ini中的参数-Xmx4096M
cd /data/tools/mat
./ParseHeapDump.sh /tmp/m.hprof org.eclipse.mat.api:suspects org.eclipse.mat.api:overview org.eclipse.mat.api:top_components
程序执行完以后会在/tmp下面生成一堆文件,其中 m_System_Overview.zip ,m_Top_Components.zip,m_Leak_Suspects.zip三个压缩文件就是报告了,可以看到程序的运行概况,最大的对象,和推测泄露点

从我的内存泄露报告中可以看到Global对象groovy.lang.MetaClassImpl对象是两个主要的内存泄露点
解决
1)复查程序发现将groovy脚本封装到了一个ThreadLocal中,在一次请求中可以被重复利用,该ThreadLocal包括了Global对象,在函数处理结束后释放掉ThreadLocal对象,主要内存泄漏点得到修复
2)groovy.lang.MetaClassImpl泄露解决,先升级groovy-all的版本
发现很多的实例其实已经没有引用了,但是内存得不到释放,当系统内存不足的时候才会被释放掉
最终解决:
- spring-boot升级到2.1.1.RELEASE
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<type>pom</type>
</dependency>
- 废用tomcat容器,改用undertow当做容器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
3)java启动参数的顺序调整
生产服务器上有些spring-boot工程的-Xmx生效,有些没有生效,并且所有的jar包jvm参数全部放到了jar包的后面
经过测试如果在本地电脑把参数放在jar包的后面是无效的
正确的写法: java -jar -Xmx2048m -Xms1024m test.jar --spring.profiles.active=prod
好的内存排查文章
[转帖]记录一次spring-boot程序内存泄露排查的更多相关文章
- 第一章 第一个spring boot程序(转载)
第一章 第一个spring boot程序 本编博客转发自:http://www.cnblogs.com/java-zhao/p/5324185.html 环境: jdk:1.8.0_73 mave ...
- 我的第一个spring boot程序(spring boot 学习笔记之二)
第一个spring boot程序 写在前面:鉴于spring注解以及springMVC的配置有大量细节和知识点,在学习理解之后,我们将直接进入spring boot的学习,在后续学习中用到注解及其他相 ...
- 构建Spring Boot程序有用的文章
构建Spring Boot程序有用的文章: http://www.jb51.net/article/111546.htm
- Spring Boot从入门到精通(一)搭建第一个Spring Boot程序
Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.通过 ...
- Spring Boot程序接收命令行参数
Spring Boot程序接收命令行参数 输入一行,回车,触发一次.如果想要调用service层,也是可以,能调用service层,就可以做很多事,触发一次就好比调用了一次http接口一样 packa ...
- Net Memory Profiler 分析.Net程序内存泄露
Net Memory Profiler 分析.Net程序内存泄露 Haozes's Tech Space 人類的全部才能無非是時間和耐心的混合物 使用.Net Memory Profiler 分析.N ...
- Spring boot程序的部署及运行
将 spring boot 应用程序打包成 jar 包 我们使用 spring boot 的 maven 插件来构建管理整个应用程序,使用 mvn package 将应用程序打包成一个 jar 包 将 ...
- Spring Boot程序的执行流程
Spring Boot的执行流程如下图所示:(图片来源于网络) 上图为SpringBoot启动结构图,我们发现启动流程主要分为三个部分,第一部分进行SpringApplication的初始化模块,配置 ...
- 第一个Spring Boot程序
Windows 10家庭中文版,java version "1.8.0_152", Eclipse Oxygen.1a Release (4.7.1a),Spring Tools ...
- Spring Boot程序正确停止的姿势
Spring Boot提供了2种优雅关闭进程的方式: 基于管理端口关闭进程 基于系统服务方式关闭进程 基于管理端口关闭进程 基于管理端口方式实现进程关闭实际上是模块spring-boot-actuat ...
随机推荐
- 你的JoinHint为什么不生效
本文分享自华为云社区<你的JoinHint为什么不生效[绽放吧!GaussDB(DWS)云原生数仓]>,作者:你是猴子请来的救兵吗 . 引言 提起数据库的Hint,几乎每个DBA都知道这一 ...
- 中秋佳节,程序员教你AI三步成诗,秒变“李白”
摘要:举杯邀明月,用技术来附庸风雅. 中秋佳节来临之际,你是否开始思念远方的亲朋好友,想为他们送上祝福?又或是与家人团圆赏月之时,希望借一段风雅诗词抒情达意? 华为云的开发者们教你一招,来个技术风的A ...
- 技术实践丨基于MindSpore的ResNet-50蘑菇“君”的识别应用体验
本文分享自华为云社区<基于MindSpore的ResNet-50蘑菇"君"的识别应用体验>,原文作者:Dasming. 摘要:基于华为MindSpore框架的ResNe ...
- 开抢| 华为开发者大会2021(Cloud)早鸟票来了!
他们,是技术的引领者 他们,是科学的追随者 他们用代码守护蓝色星球的生态 破解宇宙深处的密码 化解城市生活的不畅 捉摸自然气候的脾性 ...... 这些改变世界的成果背后 每一个开发者都了不起 --那 ...
- 拔掉电源会怎样?GaussDB(for Redis)双活让你有备无患
摘要:GaussDB(for Redis)推出双活方案,助力全球化业务部署,为您的数据资产保驾护航! 本文分享自华为云社区<华为云GaussDB(for Redis)揭秘第22期:拔掉电源会怎样 ...
- 带你了解NB-IoT标准演进
摘要:本文将带大家详细了解NB-IoT标准演进与产业发展. 本文分享自华为云社区<一文带你了解NB-IoT标准演进与产业发展>,作者:万万万. 我们都知道,物联网的场景和手机.电脑在使用的 ...
- 关于HTTPS认证,这里解决你所有疑惑
摘要:从签发证书到数据加密交互,按流程的进展讲解HTTPS认证过程内容和原理. 本文分享自华为云社区<故事+图文,一次性解决你对HTTPS认证过程的所有疑惑>,作者:breakDraw. ...
- storybook 编写stories的story基础语法
编写 stories story 用于展示组件某个状态,每个组件可以包含任意多个 story,用来测试组件的各种场景.根据默认配置,只需要在组件的文件夹中,以 **.component.stories ...
- 国内Github下载很慢,用上了这个插件后,下载速度嗖嗖嗖的~!
全球最大同性交友网站 GitHub 是所有程序员的最爱,但是国内开发者访问Github 很不稳定,克隆开源项目也慢的离谱,常常clone失败. 之前大家或绕道码云(GitLab)或修改host文件,但 ...
- 例题 5-7 丑数(Ugly Numbers,UVa 136)
题意: 丑数是一些因子只有2,3,5的数.数列1,2,3,4,5,6,8,9,10,12,15--写出了从小到大的前11个丑数,1属于丑数.现在请你编写程序,找出第1500个丑数是什么. 思路: 如果 ...