JVM 频繁 FULL GC 快速排查整理
在分享此案例前,先聊聊哪些场景会导致频繁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 快速排查整理的更多相关文章
- 一次频繁Full GC问题排查过程分享
问题描述 应用收到频繁Full GC告警 问题排查 登录到对应机器上去,查看GC日志,发现YGC一分钟已经达到了15次,比Full GC还要频繁一些,其中Full GC平均10分钟超过了4次,如下图 ...
- java面试题之----JVM架构和GC垃圾回收机制详解
JVM架构和GC垃圾回收机制详解 jvm,jre,jdk三者之间的关系 JRE (Java Run Environment):JRE包含了java底层的类库,该类库是由c/c++编写实现的 JDK ( ...
- 一次CMS GC问题排查过程(理解原理+读懂GC日志)
这个是之前处理过的一个线上问题,处理过程断断续续,经历了两周多的时间,中间各种尝试,总结如下.这篇文章分三部分: 1.问题的场景和处理过程:2.GC的一些理论东西:3.看懂GC的日志 先说一下问题吧 ...
- [转]一次CMS GC问题排查过程(理解原理+读懂GC日志)
这个是之前处理过的一个线上问题,处理过程断断续续,经历了两周多的时间,中间各种尝试,总结如下.这篇文章分三部分: 1.问题的场景和处理过程:2.GC的一些理论东西:3.看懂GC的日志 先说一下问题吧 ...
- 如何快速排查解决Android中的内存泄露问题
概述 内存泄露是Android开发中比较常见的问题,一旦发生会导致大量内存空间得不到释放,可用内存急剧减少,导致运行卡顿,部分功能不可用甚至引发应用crash.对于复杂度比较高.多人协同开发的项目来讲 ...
- JVM中的GC算法,JVM参数,垃圾收集器分类
一.在JVM中什么是垃圾?如何判断一个对象是否可被回收?哪些对象可以作为GC Roots的根 垃圾就是在内存中已经不再被使用到的空间就是垃圾. 1.引用计数法: 内部使用一个计数器,当有对象被引用+1 ...
- JVM虚拟机 与 GC 垃圾回收
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 一.JVM体系结构概述 1.JVM 与系统.硬件 JVM是运行在操作系统之上的,它与硬件没有直接的交 ...
- JVM专题3: GC 垃圾回收
合集目录 JVM专题3: GC 垃圾回收 什么是GC? 为什么要有 GC? Garbage Collection, 用于内存回收. 简述一下 Java 垃圾回收机制? 那些内存需要回收 虚拟机中程序计 ...
- JVM内存管理------GC算法精解(五分钟教你终极算法---分代搜集算法)
引言 何为终极算法? 其实就是现在的JVM采用的算法,并非真正的终极.说不定若干年以后,还会有新的终极算法,而且几乎是一定会有,因为LZ相信高人们的能力. 那么分代搜集算法是怎么处理GC的呢? 对象分 ...
- JVM内存管理------GC简介
为何要了解GC策略与原理? 原因在上一章其实已经有所触及,就是因为在平时的工作和研究当中,不可避免的会遇到内存溢出与内存泄露的问题.如果对GC策略与原理不了解的情况下碰到了前面所说的问题,很多时候会让 ...
随机推荐
- Mysql学习:2、mysql基本命令
1.下载安装好的mysql分为两种数据库: a.系统自带: b.用户自己创建: 2.基本命令: create database 数据库名称; // 创建数据库:记住后面加 分号 drop databa ...
- css 背景渐变
1.渐变从左到右 background: linear-gradient(to right,#000,#fff); 2.渐变从上到下 background: linear-gradient(tobot ...
- Java8:LocalDate/ LocalDateTime与String、Date、TimeStamp的互转
LocalDate与String.Date.TimeStamp的互转: LocalDateTime与String.Date.TimeStamp的互转: 结果如下: 附代码: public static ...
- gets,fgets,getchar,fgetc
以上四个函数都是读取外部输入的函数.可以使stdin,也可以是文件.以下都是在C语言中的应用 关于gets和fgets都能够读取一行,一行结束的标志是"回车".都有弊端gets(s ...
- iOS界面横屏竖屏随意切换
转https://www.jianshu.com/p/ea1682e80003 先讲需求: APP中所有界面支持竖屏,只有在一个界面,点击一个btn之后变成横屏,再点就是竖屏.在网上找了一些方法,发现 ...
- java 操作excel
需要引入的包 import org.apache.poi.hssf.usermodel.*; import org.apache.poi.ss.usermodel.HorizontalAlignmen ...
- Java Fastjson Unserialize WriteUp
Java Fastjson Unserialize 题目地址: https://ctf.bugku.com/challenges/detail/id/339.html 1. 查看网页源代码 <s ...
- software engineering homework 2
博客信息 沈阳航空航天大学计算机学院2020软件工程作业 作业要求 https://edu.cnblogs.com/campus/sau/Computer1701-1705/homework/1058 ...
- 修改allure图标和标题
allure的logo更换步骤 1.找到allure安装目录,进入目录如:D:\Program Files\allure-2.17.3\plugins\custom-logo-plugin\stati ...
- SQL Server 还原数据库
1.备份要还原的数据库 选择要备份的数据库,右键单击,任务--备份. 2.备份完成后,将数据库还原 3.新建一个空的数据库,比如Gsy_TestNew,将备份的数据库还原到这个新的库上 4.右键单击[ ...