在分享此案例前,先聊聊哪些场景会导致频繁Full GC:

内存泄漏(代码有问题,对象引用没及时释放,导致对象不能及时回收)
死循环
大对象
程序执行了System.gc()

尤其是大对象,80%以上的情况就是他。  那么大对象从哪里来的:
【1】数据库(包括 Mysql和 Mongodb等 NOSql数据库),结果集太大;
【2】第三方接口传输的大对象;
【3】消息队列,消息太大;

根据多年一线互联网经验,绝大部分情况是数据库大结果集导致。好,现在我们开始介绍这次线上故障:

在没有任何发布的情况下,POP(point of purchase的缩写bai,意为“卖点广告”其主要商du业用途是刺激引导zhi消费和活跃dao卖场气氛)服务(接入第三方商家的服务)突然开始疯狂Full GC,观察堆内存监控没内存泄漏,回滚到前一版本,问题仍然存在,尴尬了!!!

按照常规做法,一般先用 jmap导出堆内存快照(jmap -dump:format=b,file=文件名 [pid]),然后用 mat等工具分析出什么对象占用了大量空间,再查看相关引用找到问题代码。为了进一步排查原因,我们在线上开启了 -XX:+HeapDumpBeforeFullGC在其中一台机子上开启了 -XX:HeapDumpBeforeFullGC,总体JVM参数如下:

 1 -Xmx2g
2 -XX:+HeapDumpBeforeFullGC
3 -XX:HeapDumpPath=.
4 -Xloggc:gc.log
5 -XX:+PrintGC
6 -XX:+PrintGCDetails
7 -XX:+PrintGCDateStamps
8 -XX:+UseGCLogFileRotation
9 -XX:NumberOfGCLogFiles=10
10 -XX:GCLogFileSize=100m
11 -XX:HeapDumpOnOutOfMemoryError

注意:JVM 在执行 dump操作的时候是会发生 stop the word事件的,也就是说此时所有的用户线程都会暂停运行。为了在此期间也能对外正常提供服务,建议采用分布式部署,并采用合适的负载均衡算法

dump下来的文件大约 1.8g,用 jvisualvm查看,发现用 char[]类型的数据占用了41%内存,同时另外一个 JdbcSqlStat类型的数据占用了35%的内存,也就是说整个堆中几乎全是这两类数据。如下图:

查看char[]类型数据,发现几乎全是sql语句:

接下来查看char[]的引用情况:并对代码进行修改

这种方式定位问题周期会比较长,如果是关键服务,长时间不能定位解决问题,影响太大。

下面来看看我们的做法。先按照常规做法分析堆内存快照,与此同时另外的同学去查看数据库服务器网络IO监控,如果数据库服务器网络IO有明显上升,并且时间点吻合,基本可以确定是数据库大结果集导致了Full GC,赶紧找DBA快速定位大SQL(对DBA来说很简单,分分钟搞定,如果DBA不知道怎么定位,那他要被开除了,哈哈),定位到 SQL后再定位代码就非常简单了。按照这种办法,我们很快定位了问题。原来是一个接口必传的参数没传进来,也没加校验,导致 SQL语句 where后面少了两个条件,一次查几万条记录出来,真坑啊!这种方法是不是要快很多,哈哈,5分钟搞定。

当时的 DAO层是基于 Mybatis实现的,出问题的SQL语句如下:

1 <select id="selectOrders" resultType="com.***.Order" >
2 select * from user where 1=1
3 <if test=" orderID != null ">and order_id = #{orderID}</if >
4 <if test="userID !=null">and user_id=#{userID}</if >
5 <if test="startTime !=null">and create_time >= #{createTime}</if >
6 <if test="endTime !=null">and create_time <= #{userID}</if >
7 </select>

上面SQL语句意思是根据 orderID查一个订单,或者根据 userID查一个用户所有的订单,两个参数至少要传一个。但是两个参数都没传,只传了 startTime和 endTime。所以一次 Select就查出了几万条记录。所以我们在使用 Mybatis的时候一定要慎用 if test,一不小心就会带来灾难。后来我们将上面的SQL拆成了两个:

根据订单ID查询订单:

1 <select id="selectOrderByID" resultType="com.***.Order" >
2 select * from user where
3 order_id = #{orderID}
4 <if test="startTime !=null">and create_time >= #{createTime}</if >
5 <if test="endTime !=null">and create_time <= #{userID}</if >
6 </select>

根据 userID查询订单:

1 <select id="selectOrdersByUserID" resultType="com.***.Order" >
2 select * from user whereuser_id=#{userID}
3 <if test="startTime !=null">and create_time >= #{createTime}</if >
4 <if test="endTime !=null">and create_time <= #{userID}</if >
5 </select>

JVM 频繁 FULL GC 快速排查整理的更多相关文章

  1. 一次频繁Full GC问题排查过程分享

    问题描述 应用收到频繁Full GC告警 问题排查 登录到对应机器上去,查看GC日志,发现YGC一分钟已经达到了15次,比Full GC还要频繁一些,其中Full GC平均10分钟超过了4次,如下图 ...

  2. java面试题之----JVM架构和GC垃圾回收机制详解

    JVM架构和GC垃圾回收机制详解 jvm,jre,jdk三者之间的关系 JRE (Java Run Environment):JRE包含了java底层的类库,该类库是由c/c++编写实现的 JDK ( ...

  3. 一次CMS GC问题排查过程(理解原理+读懂GC日志)

    这个是之前处理过的一个线上问题,处理过程断断续续,经历了两周多的时间,中间各种尝试,总结如下.这篇文章分三部分: 1.问题的场景和处理过程:2.GC的一些理论东西:3.看懂GC的日志 先说一下问题吧 ...

  4. [转]一次CMS GC问题排查过程(理解原理+读懂GC日志)

    这个是之前处理过的一个线上问题,处理过程断断续续,经历了两周多的时间,中间各种尝试,总结如下.这篇文章分三部分: 1.问题的场景和处理过程:2.GC的一些理论东西:3.看懂GC的日志 先说一下问题吧 ...

  5. 如何快速排查解决Android中的内存泄露问题

    概述 内存泄露是Android开发中比较常见的问题,一旦发生会导致大量内存空间得不到释放,可用内存急剧减少,导致运行卡顿,部分功能不可用甚至引发应用crash.对于复杂度比较高.多人协同开发的项目来讲 ...

  6. JVM中的GC算法,JVM参数,垃圾收集器分类

    一.在JVM中什么是垃圾?如何判断一个对象是否可被回收?哪些对象可以作为GC Roots的根 垃圾就是在内存中已经不再被使用到的空间就是垃圾. 1.引用计数法: 内部使用一个计数器,当有对象被引用+1 ...

  7. JVM虚拟机 与 GC 垃圾回收

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 一.JVM体系结构概述 1.JVM 与系统.硬件 ​ JVM是运行在操作系统之上的,它与硬件没有直接的交 ...

  8. JVM专题3: GC 垃圾回收

    合集目录 JVM专题3: GC 垃圾回收 什么是GC? 为什么要有 GC? Garbage Collection, 用于内存回收. 简述一下 Java 垃圾回收机制? 那些内存需要回收 虚拟机中程序计 ...

  9. JVM内存管理------GC算法精解(五分钟教你终极算法---分代搜集算法)

    引言 何为终极算法? 其实就是现在的JVM采用的算法,并非真正的终极.说不定若干年以后,还会有新的终极算法,而且几乎是一定会有,因为LZ相信高人们的能力. 那么分代搜集算法是怎么处理GC的呢? 对象分 ...

  10. JVM内存管理------GC简介

    为何要了解GC策略与原理? 原因在上一章其实已经有所触及,就是因为在平时的工作和研究当中,不可避免的会遇到内存溢出与内存泄露的问题.如果对GC策略与原理不了解的情况下碰到了前面所说的问题,很多时候会让 ...

随机推荐

  1. opencv基本函数详解笔记

    一.读取保存图片 Mat scrImage = imread("1.jpg"); //显示图像 imshow("原图", scrImage); //窗口等待 w ...

  2. 法拉第未来任命新CFO!贾跃亭激动发声

    近段时间以来,贾跃亭旗下的的法拉第未来(Faraday Future,简称 FF)可谓是动作频频. 一天前,有媒体报道称,FF 任命 Zvi Glasman 为其首席财务官.其将负责公司财务.投资者关 ...

  3. 5 RDD编程

    一.词频统计 1.读文本文件生成RDD lines 2.将一行一行的文本分割成单词 words flatmap() 3.全部转换为小写 lower() 4.去掉长度小于3的单词 filter() 5. ...

  4. vscode python配置pip源

    更换到国内清华园 C盘-User-用户名-新建"pip"文件夹-新建"pip.ini"文件 pip.ini 文件中内容: [global]index-url = ...

  5. Vue项目目录树

  6. c 理解

    exit() 的含义:提前结束程序 .c 文件 return的含义 :提前结束函数,其所在行以下,整体大函数底花括号以上,2者之间的所有语句都不会被执行到,用它来提前结束程序. break的含义 :提 ...

  7. python3GUI--200行代码写一个上课点名程序(附源码)

    @ 目录 一.准备工作 1.Tkinter 2.PIL 二.预览 1.启动 2.开始点名-顺序点名 3.开始点名-随机点名 4.手动加载人名单 5.开始点名-顺序点名-Pyqt5版本 6.人名单格式 ...

  8. C语言初级阶段5——函数1

    C语言初级阶段5--函数1 函数的基本概念 1.函数:理解为封装功能的容器. 主函数是函数的入口 2.函数定义的基本格式: 返回值类型:常用的基本数据类型,执行完以后,函数会得到一个什么类型的值,如果 ...

  9. 10.14 2020 实验 7:OpenDaylight 实验——Python 中的 REST API 调用

    一.实验目的  对 Python 调用 OpenDaylight 的 REST API 方法有初步了解.   二.实验任务  本实验需要用另一种方法完成上一个实验相同的功能,即通过 Python 程序 ...

  10. 将 Sql Server 表信息 C# 对象化 小工具_ 张光荣 的 正能量

    注: a.此程序所得到的结果是根据本人个人习惯生成,所以,肯定不完全适合所有人使用,重在想法...然后个人根据个人需求作出更进...b.程序中可能会出现数据库连接的错误提示[原因概是在sql 连接过程 ...