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策略与原理不了解的情况下碰到了前面所说的问题,很多时候会让 ...
随机推荐
- 1.3 C语言--指针与结构体
指针 指针概念的引入 关于内存 程序有数据和指令组成,数据和指令在执行过程中存放在内存中.变量是程序数据中的一种,因此变量也存储在内存中:内存中的每个字节都有一个唯一的编码,即内存地址.32位机的内存 ...
- backward函数中gradient参数的一些理解
当标量对向量求导时不需要该参数,但当向量对向量求导时,若不加上该参数则会报错,显示"grad can be implicitly created only for scalar output ...
- Kafka相关问题
Kafka有哪几个部分组成 生产者.消费者.topic.group.partition kafka的group1)定义:即消费者组是 Kafka 提供的可扩展且具有容错性的消费者机制.在Kafka中, ...
- dpkt 简单应用
import dpktfrom dpkt.utils import mac_to_str,inet_to_strcap=f'D:/test_pacp/6.pcap'with open(cap,'rb' ...
- JAVA 、Http协议:
JAVA如何配置服务器: Http协议: 1.什么是Http协议 HTTP,超文本传输协议(HyperText Transfer Protocol)是互联网上应用最为广泛的 一种网络协议.所有的W ...
- 页面与java后台之 上传文件与服务器加载
添加相关依赖包commons-fileupload等: 页面(注:编码enctype="multipart/form-data" 文件按钮属性multiple) java ...
- 11.30linux学习第十一天
今天老刘上课,第7章收尾,第8章开了个头. 7.1.3 磁盘阵列+备份盘 RAID 10磁盘阵列中最多允许50%的硬盘设备发生故障,但是存在这样一种极端情况,即同一RAID 1磁盘阵列中的硬盘设备若 ...
- js两个数组对象合并去重
- FCC 中级算法题 数组扁平化
Steamroller 对嵌套的数组进行扁平化处理.你必须考虑到不同层级的嵌套. Array.isArray() 思路: (1)遍历arr,如果arr[i]是数组,就重新调用本函数继续循环,然后和新数 ...
- css scoped和moudle
scoped css 官方文档 缺点 一.如果用户在别处定义了相同的类名,也许还是会影响到组件的样式. 二.根据css样式优先级的特性,scoped这种处理会造成每个样式的权重加重了: 即理论上我们要 ...