排查Java进程内存占比过高的方法

 更新时间:2023年10月18日 08:38:49   作者:在下uptown  
某天下午运维反应集成环境的一个Java服务内存飙高,内存耗的太高了,会疑似内存泄漏,所以本文记一次排查Java进程内存占比过高的解决方法,需要的朋友可以参考下

前言

早期面试的时候最害怕面试官问有没有过JVM调优的经验,一听这个问题腿肚子直转筋,JVM八股文都没背多熟练呢,调啥优啊,唠嗑唠的让人害怕,工作一段时间发现不就是基于服务当时所在环境和现象根据JVM现有参数调参嘛,今天记一个JVM内存相关参数。

某天下午运维反应集成环境的一个Java服务内存飙高,看到消息我第一反应就是高就高呗,这不Java本身的特点,高你就多让给它点内存得了,嫌高用Go重构。后来运维说内存耗的太高了,疑似内存泄漏。那得认真分析一波了,别到时候上线发版出了大问题,事关众后端将士的绩效高低,我义不容辞。

内存分析

排查Java进程三板斧,先TOP看资源情况,shit+M按内存排序看是个用户中心的服务,当时看用了接近20G左右,非常高了,集成环境都是研发测试用的环境,没有多少访问量怎么会有这么高的内存使用量。看来多半是泄露了。

分析内存泄露其实也不难,我们先拿到pid浅浅的运行下

jmap -histo:live [pid] > a.txt

这是获取当前进程中存活的对象统计并把结果输出到a.txt中,从高到低排序,直接看排在前几位的对象有没有我们的业务对象,如果有的话那差不多就逮到了,顺着这个类找一下对应的逻辑分析一下基本就能定位到。但是执行完查询发现排在前几位都是jdk中的class,第一位是c[([代表数组,char[]数组最多也正常,因为String底层就是char[],而且String应用的地方也比较多)

这里已经开始挠头了,不太对啊,按理说内存泄漏肯定是业务中用的类占比会多,再不济也应该是map占用高,这里明显不太符合泄露的现象。。。

分析一下每5s的gc情况发现也都很平稳。

jstat -gc pid 5000

那只能分析dump文件了,可以借助fastThread.io分析dump,也可以搞个JProfile分析。

jmap -dump pid

dump之后导入Jprofile发现整体内存占用才2G多,这就很诡异了,从现象上来看像是假装用了20g内存实际只用了2g,这是咋回事呢。

解决方案

本质上是jvm是在启动的时候就会向操作系统申请一部分内存,然后占着自己再做内存管理,当分配对象被回收之后也只是在这个内存区域清除数据然后标记空闲,也就是说根本不会归还给操作系统。根本原因是归还操作系统成本较高,不同的垃圾回收器也有不同的规则。

一直占着也不是个事,JVM还是提供了设置归还策略的参数,MaxHeapFreeRatio,当空闲区域超过该值时,会进行内存回收,剩余空间的下限为Xms,回收的过程也是线性回收并不是到点下班,到了MaxHeapFreeRatio内存立马降下来。

根据网上大佬们的结论,不同的垃圾回收器下的表现也不一样,详细的结论大家可以自行再去研究。

JAVA 版本垃圾回收器参数是否可以“归还”
JAVA 8ParallerGC + ParallerOld-Xms100M -Xmx2G -XX:MaxHeapFreeRatio=40
JAVA 8CMS+ParNew-Xms100M -Xmx2G -XX:MaxHeapFreeRatio=40 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC
JAVA 8G1-Xms100M -Xmx2G -XX:MaxHeapFreeRatio=40 -XX:+UseG1GC
JAVA 11G1-Xms100M -Xmx2G -XX:MaxHeapFreeRatio=40

根据以上结论将服务启动命令增加了-XX:++UseG1GC -XX:MaxHeapFreeRatio=50(最大空闲比例超过50%归还)参数后内存过高的问题的确没有再出现。

到此这篇关于排查Java进程内存占比过高的方法的文章就介绍到这了,更多相关Java进程内存占比过高内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Struts2数据输入验证教程详解

    Struts2数据输入验证教程详解

    这篇文章主要介绍了Struts2数据输入验证教程详解的相关资料,输入数据验证的方法有两种,本文给大家介绍的非常详细,需要的朋友可以参考下
    2016-10-10
  • Spring Boot 多数据源处理事务的思路详解

    Spring Boot 多数据源处理事务的思路详解

    这篇文章主要介绍了Spring Boot 多数据源如何处理事务,本文单纯就是技术探讨,要从实际应用中来说的话,我并不建议这样去玩分布式事务、也不建议这样去玩多数据源,毕竟分布式事务主要还是用在微服务场景下,对Spring Boot 多数据源事务相关知识感兴趣的朋友参考下本文
    2022-06-06
  • 一文教你搞定Java Optional类判空操作

    一文教你搞定Java Optional类判空操作

    有时项目组内做code review,会充斥着大量的、原始的、丑陋的判空语句。让整体的代码显得十分的臃肿庞大丑陋,那么怎么办呢?利用Optional这个jdk8中引入的类就可以优雅的处理,现在我们来详细讲解下这个类的使用和源码
    2022-10-10
  • java基础之初始化ArrayList时直接赋值的4种方式总结

    java基础之初始化ArrayList时直接赋值的4种方式总结

    ArrayList是Java中的一个类,它是Java集合框架中的一部分,用于实现动态数组,下面这篇文章主要给大家介绍了关于java基础之初始化ArrayList时直接赋值的4种方式,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-07-07
  • Java如何实现Word文档分栏效果

    Java如何实现Word文档分栏效果

    这篇文章主要介绍了Java如何实现Word文档分栏效果,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-05-05
  • 基于Java Springboot + Vue + MyBatis实现音乐播放系统

    基于Java Springboot + Vue + MyBatis实现音乐播放系统

    这篇文章主要介绍了一个完整的音乐播放系统是基于Java Springboot + Vue + MyBatis编写的,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-08-08
  • JAVA多种方法实现字符串反转

    JAVA多种方法实现字符串反转

    大家好,本篇文章主要讲的是JAVA多种方法实现字符串反转,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2022-01-01
  • Java比较对象大小两种常用方法

    Java比较对象大小两种常用方法

    这篇文章主要介绍了Java比较对象大小两种常用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • SpringBoot加载多个配置文件实现dev、product多环境切换的方法

    SpringBoot加载多个配置文件实现dev、product多环境切换的方法

    这篇文章主要介绍了SpringBoot加载多个配置文件实现dev、product多环境切换,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-03-03
  • java发送邮件示例讲解

    java发送邮件示例讲解

    这篇文章主要为大家详细介绍了java发送邮件示例的全过程,温习邮件协议,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-03-03

最新评论