现象

spring boot项目jvm启动配置-Xms4g -Xmx4g,然而很不幸的是程序所占的内存越来越高,都达到了12个多G,只能临时重启服务

常用命令

  • jstat -class PID
  • jstat -compiler PID
  • jstat -gc PID
  • jstat -gccapacity PID
  • jstat -gcutil PID 查看堆比例
  • jstat -gccause PID
  • jstat -gcnew PID
  • jstat -gcnewcapacity PID
  • jstat -gcold PID
  • jstat -gcoldcapcacity PID
  • jstat -printcompilation PID
  • jmap -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进程实例最多的类

  1. 本机启动程序,postman或者jmeter调用程序接口,可以直接直接用jvisualvm查看到堆栈信息
  2. 远程调试,在测试环境启用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引起的“堆外内存泄漏”排查及经验总结

文章知识点与官方知识档案匹配,可进一步学习相关知识
Java技能树首页概览104410 人正在系统学习中

[转帖]记录一次spring-boot程序内存泄露排查的更多相关文章

  1. 第一章 第一个spring boot程序(转载)

    第一章 第一个spring boot程序 本编博客转发自:http://www.cnblogs.com/java-zhao/p/5324185.html   环境: jdk:1.8.0_73 mave ...

  2. 我的第一个spring boot程序(spring boot 学习笔记之二)

    第一个spring boot程序 写在前面:鉴于spring注解以及springMVC的配置有大量细节和知识点,在学习理解之后,我们将直接进入spring boot的学习,在后续学习中用到注解及其他相 ...

  3. 构建Spring Boot程序有用的文章

    构建Spring Boot程序有用的文章: http://www.jb51.net/article/111546.htm

  4. Spring Boot从入门到精通(一)搭建第一个Spring Boot程序

    Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.通过 ...

  5. Spring Boot程序接收命令行参数

    Spring Boot程序接收命令行参数 输入一行,回车,触发一次.如果想要调用service层,也是可以,能调用service层,就可以做很多事,触发一次就好比调用了一次http接口一样 packa ...

  6. Net Memory Profiler 分析.Net程序内存泄露

    Net Memory Profiler 分析.Net程序内存泄露 Haozes's Tech Space 人類的全部才能無非是時間和耐心的混合物 使用.Net Memory Profiler 分析.N ...

  7. Spring boot程序的部署及运行

    将 spring boot 应用程序打包成 jar 包 我们使用 spring boot 的 maven 插件来构建管理整个应用程序,使用 mvn package 将应用程序打包成一个 jar 包 将 ...

  8. Spring Boot程序的执行流程

    Spring Boot的执行流程如下图所示:(图片来源于网络) 上图为SpringBoot启动结构图,我们发现启动流程主要分为三个部分,第一部分进行SpringApplication的初始化模块,配置 ...

  9. 第一个Spring Boot程序

    Windows 10家庭中文版,java version "1.8.0_152", Eclipse Oxygen.1a Release (4.7.1a),Spring Tools ...

  10. Spring Boot程序正确停止的姿势

    Spring Boot提供了2种优雅关闭进程的方式: 基于管理端口关闭进程 基于系统服务方式关闭进程 基于管理端口关闭进程 基于管理端口方式实现进程关闭实际上是模块spring-boot-actuat ...

随机推荐

  1. 基于KubeEdge的边缘节点分组管理设计与实现

    摘要:KubeEdge 1.11版本提供了"边缘节点分组管理"新特性,抽象出了跨地域的应用部署模型. 本文分享自华为云社区<基于KubeEdge的边缘节点分组管理设计与实现& ...

  2. 资深Linux 系统管理员常用的15个很好用的Cron工作示例

    摘要:Linux Cron 实用程序是一种在特定时间和/或日期持续调度例行后台作业的有效方法.这篇文章讲述了15 个很好用的 crontab 工作调度示例. 本文分享自华为云社区<Linux C ...

  3. 想了解Xtrabackup备份原理和常见问题分析,看这篇就够了

    摘要:本文来自华为云MySQL研发团队,主要分享了MySQL备份工具Xtrabackup的备份过程.华为云数据库团队对其做的优化改进,以及在使用中可能遇到的问题与解决方法. 本文分享自华为云社区< ...

  4. 华为云GaussDB深耕数字化下半场,持续打造数据库根技术

    摘要:华为云数据库CTO庄乾锋携华为云数据库多位技术专家和优秀合作伙伴共同参与DTCC2021大会并发表了重要主题演讲. 10月18日,以"数造未来"为主题的第12届中国数据库技术 ...

  5. target.closest妙用:UI(click/mousemove/drag/drop)事件元素查找捷径

    首先看下MDN:https://developer.mozilla.org/en-US/docs/Web/API/Element/closest 在jQuery时代,这个非常常见 $( documen ...

  6. 【终极教程】Cocos2dx服务端重构(优化cocos2dx服务端)

    [终极教程]Cocos2dx服务端重构(优化cocos2dx服务端) 文章目录 概述 问题概述1. 代码混淆代码加密具体步骤测试和配置阶段IPA 重签名操作步骤2. 缺乏文档3. 缺乏推荐的最佳实践4 ...

  7. DataLeap的全链路智能监控报警实践(一):常见问题

    随着字节跳动业务的快速发展,大数据开发场景下需要运维管理的任务越来越多,然而普通的监控系统只支持配置相应任务的监控规则,已经不能完全满足当前需求,在日常运维中开发者经常会面临以下几个问题: 任务多,依 ...

  8. 【HZERO】数据导入

    #数据导入 ##文档整理 通用导入客户端 https://open.hand-china.com/hzero-docs/v1.3/zh/docs/service/import/import/ 开放平台 ...

  9. CMakeLists.txt的工程转成.sln

    直接说正确的操作(结合之前的笔记) 创建 Build 目录 mkdir build && cd build 执行 cmake 命令,根据 CMakeLists.txt 生成 .sln ...

  10. 3.1 《数据库系统概论》SQL概述及数据定义(模式SCHEMA、表TABLE、索引INDEX)

    前言 本篇文章学习书籍:<数据库系统概论>第5版 王珊 萨师煊编著 视频资源来自:数据库系统概论完整版(基础篇+高级篇+新技术篇) 由于 BitHachi 学长已经系统的整理过本书了,我在 ...