概述

又是一次因为线上报警机制开启的排查问题之旅。某日,钉钉机器人疯狂报警:

接着就是申请机器权限去排查问题,既然是频繁Full GC,那我们排查问题的思路就应该是找到引起Full GC的原因。引起频繁Full GC的常见原因有这么几点:

  1. 堆外内存达到阈值,将会调用System.gc()来做一次Full GC。这里说的堆外内存主要说的是nio下的DirectByteBuffer,它会通过Unsafe接口通过os::malloc来分配内存,然后将内存的起始地址和大小存到DirectByteBuffer对象中,只有当DirectByteBuffer被回收掉之后堆外内存才可能被回收。具体堆外内存回收的细节大家可以看下笨神的JVM源码分析之堆外内存完全解读.
  2. 项目中显示或隐式的调用了System.gc()。System.gc的详情可见链接描述
  3. 老年代可用空间不够了,导致它的原因有多种,但是常见的排查思路通过mat去分析堆内存dump文件。

定位Full GC的原因

gc日志永远都是我们排查gc问题最好的工具,所以强烈建议大家在线上配置-XX:+PrintGCDetails -Xloggc:/data/logs/gc.log方便我们去定位问题。由于当前项目没有配置,只好用jstat -gccause去监测,博主监测了五分钟左右,得到如下信息:新生代、老年代、元空间内存还很多,FGC涨了9次,并且对应的LGCC都显示为System.gc.由于虚拟机参数并没有去配置-XX:MaxDirectMemorySize,所以其堆外内存受限于当前物理机内存,故我们可以通过top去查看进程占了多少内存和通过free -m查看空闲内存(当然visualvm的插件和perftools都是查看堆外内存使用情况很好的工具,不了解自行谷歌)。经过内存分析和业务分析之后,初步断定不是堆外内存导致的,而是由项目中有调用System.gc().

如何查找项目哪里有调用Full GC呢

首先对项目全局进行搜索System.gc(),如果没有查到,那么就很可能是依赖的jar包里存在调用,如何在jar包中查找呢?在这里给大家推荐一款插件Btracegithub地址。BTrace是Java的安全可靠的动态跟踪工具。 他的工作原理是通过 instrument + asm 来对正在运行的java程序中的class类进行动态增强。说他是安全可靠的,是因为它对正在运行的程序是只读的。也就是说,他可以插入跟踪语句来检测和分析运行中的程序,不允许对其进行修改。因此他存在一些限制:


  1. 不能创建对象
  2. 不能创建数组
  3. 不能抛出和捕获异常
  4. 不能调用任何对象方法和静态方法
  5. 不能给目标程序中的类静态属性和对象的属性进行赋值
  6. 不能有外部、内部和嵌套类
  7. 不能有同步块和同步方法
  8. 不能有循环(for, while, do..while)
  9. 不能继承任何的类
  10. 不能实现接口
  11. 不能包含assert断言语句

根据官方声明,不恰当的使用Btrace会导致jvm崩溃,所以在上生产环境之前,一定要在本地充分验证脚本的正确性。Btrace的常见使用场景有:

  1. 分析哪些方法调用System.gc,获取其调用栈
  2. 接口性能差,分析耗时情况
  3. 当出现异常时,分析方法的运行时参数
  4. 线上有一个大对象ArrayList,查看其内容

安装使用Btrace

Btrace依赖于JDK,首先要安装好JDK并配置JDK的环境变量。

1.下载安装包

下载地址:https://github.com/btraceio/btrace/releases/tag/v1.3.11

2.解压缩


修改目录权限:

3.配置环境变量

然后source更新环境变量
4.编写btrace脚本

import static com.sun.btrace.BTraceUtils.jstack;
import static com.sun.btrace.BTraceUtils.println;
import static com.sun.btrace.BTraceUtils.str;
import static com.sun.btrace.BTraceUtils.strcat;
import static com.sun.btrace.BTraceUtils.timeMillis;import com.sun.btrace.annotations.BTrace;
import com.sun.btrace.annotations.Kind;
import com.sun.btrace.annotations.Location;
import com.sun.btrace.annotations.OnMethod;
import com.sun.btrace.annotations.TLS;
@BTrace
public class MyTest {@OnMethod(clazz = "java.lang.System", method = "gc" )public static void startMethod(){println("****************************************");jstack();println("****************************************");}@OnMethod(clazz = "java.lang.System", method = "gc", location = @Location(Kind.RETURN))public static void endMethod(){println("=========================================");jstack();println("=========================================");}
}

5.运行btrace

通过jps -l获得进程的pid,然后通过 btrace <pid> <btrace_script> >> gc.txt & 以后台任务的方式去开启btrace脚本监听对应进程,将对应的栈信息保存到gc.txt中。
6.关闭btrace


经过长达一天的监控,终于抓到了对应的调用栈:


原因是项目中用到了jxl的Workbook来做Excel相关的功能,每次关闭Workbook的时候都会调用System.gc

至此,我们就已经抓住了导致频繁Full GC的鬼了,改动方法也特别简单,在构造WorkBook的时候,将其成员变量WorkbookSettings的成员变量gcDisabled设置为true即可避免此问题,或者添加vm参数-Djxl.nogc=true(不太推荐).

通过btrace排查线上频繁Full GC的case 1相关推荐

  1. 通过btrace排查线上频繁Full GC的case

    概述 又是一次因为线上报警机制开启的排查问题之旅.某日,钉钉机器人疯狂报警: 接着就是申请机器权限去排查问题,既然是频繁Full GC,那我们排查问题的思路就应该是找到引起Full GC的原因.引起频 ...

  2. 线上频繁发生Full GC 如何调优?如何快速定位OOM、cpu飙升、线程死锁等问题

    文章目录 1. jvm调优命令.工具介绍 ①:jps ②:jmap 查看应用中各实例生成情况 快速定位内存突然飙升导致的OOM异常 查看堆内存使用情况 ③:Jstack 检测线程死锁 快速定位导致cp ...

  3. php线上问题排查,线上问题排查神器 Arthas

    摘要: rController|kite.springcloud.jxm.service.MonitorDashboardServiceoverviewstack输出当前方法被调用的调用路径stack ...

  4. 阿里技术:如何快速排查线上故障?

    阿里技术:如何快速排查线上故障? 以下文章来源于阿里技术 ,作者小峯 阿里技术 阿里巴巴官方技术号,关于阿里的技术创新均呈现于此. 有哪些常见的线上故障?如何快速定位问题?本文详细总结工作中的经验,从 ...

  5. 频繁gc是什么意思_[JVM]一次线上频繁GC的问题解决

    起因:周末测试发现线上mq消息积压了十几万的消息,如下图所示 每个队列几万的消息,立即采取紧急措施,将队列下线重新上线. 处理积压消息的量,调用量起来了,很快消息积压解决了.开始事件复盘. 首先分析是 ...

  6. 线上频繁GC怎么处理

    1.故障突发 频繁GC会导致接口变慢,系统明显卡顿.首先当然是以最快的速度恢复系统的正常使用,然后组织相关干系人进行快速决策会议,进行事故原因排查,定位问题的根本原因. 2.故障恢复 1.先查看是否是 ...

  7. 记一次排查线上full gc过程

    序 最近频繁收到线上报警,就看看到底啥原因 二 导出dump文件 2.1 查找报警对应的进程 ps -ef|grep XX 是23898,看一下gc情况: 这才不到半小时,fgc就增加了好几次. jm ...

  8. 利用神器BTrace 追踪线上 Spring Boot应用运行时信息

    可用于追踪线上 Java服务 运行时信息的神器 BTrace,你们经常用吗 ? 概述 生产环境中的服务可能会出现各种问题,但总不能让服务下线来专门排查错误,这时候最好有一些手段来获取程序运行时信息,比 ...

  9. docker容器cpu高问题排查_干货详解:一文教你如何利用阿里开源工具,排查线上CPU居高问题...

    前言 在我们开发过程中,无法避免的会出现所谓的垃圾代码,导致服务器的CPU一直处于100%.但我们应用已经上线,导致服务器CPU居高,但又不知道哪边出现的问题,我们应该怎么去找出哪边的代码出现问题呢? ...

最新文章

  1. mysql 查看表结构,字段的基本信息(简单明了)。
  2. ‘torch.nn‘ has no attribute ‘SiLU‘
  3. java arraylist 源代码_Java中ArrayList源码浅析
  4. Android—Navigation的使用
  5. 告别 ROR windows 部署的噩梦-在 windows 上面 使用 Apache 部署 Ruby On Rails
  6. 阿里云视频云 Retina 多媒体 AI 体验馆开张啦
  7. python中with的用法简单来说_Python中with的用法
  8. 苹果新一代 AirPods 能活过两年吗?
  9. 解决WEB页面上焦点控制一法
  10. 大量数据table_一次 SQL 查询优化原理分析(900W+ 数据,从 17s 到 300ms)
  11. Java编程:爬楼梯问题、斐波那契数列问题
  12. 打造炫酷通用的ViewPager指示器 玩转字体变色
  13. 千万不能返回局部变量的引用
  14. 计算机专业可以转英语吗,计算机专业英语词汇转.doc
  15. 我的实用小软件(持续更新)
  16. 春节要闻回顾 | 数字人民币和元宇宙被搬上春晚;美国财政部报告警告NFT可用于洗钱...
  17. 关于easyx库中怎样贴出透明图片
  18. 微型计算机显示器的两种引线,第八章章节微型计算机接口技术8-2led显示器接口.ppt...
  19. Android studio sdk下载
  20. 简单使用Linux工业平板(一)

热门文章

  1. (*长期更新)软考网络工程师学习笔记——Section 14 Linux服务器配置
  2. 映射文件_Hibernate 映射文件
  3. 实验详解——parted单磁盘分区并进行配额
  4. 成为进阶Linux大佬的第一步
  5. android7.1 shotcuts,Android N App Shotcuts 学习
  6. join和group by能一块用吗_冷冻一下地球能缓解温室效应吗?| No.171
  7. ajax局部刷新_web前端入门到实战:实现html页面自动刷新
  8. xmind怎么在左边创建_个人怎么做微信小程序商城
  9. java中hashcode作用_Java中hashCode的作用
  10. linux脚本 set env,linux 中 set,env,export,declare显示shell变量的区别