记一次 stackoverflowerror 线上排查过程

这篇具有很好参考价值的文章主要介绍了记一次 stackoverflowerror 线上排查过程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一.线上 stackOverFlowError

记一次 stackoverflowerror 线上排查过程,【项目实战】,后端,java,stackoverflow

    xxx日,突然收到线上日志关键字频繁告警 classCastException.从字面上的报警来看,仅仅是类型转换异常,查看细则发现其实是 stackOverFlowError.很多同学面试的时候总会被问到有没有遇到过线上stackOverFlowError?有么有遇到栈溢出?具体栈溢出怎么来解决?今天他来了,他带着问题走来了.话不说多,直入正题.具体打印的stackOverFlowError细则如下

记一次 stackoverflowerror 线上排查过程,【项目实战】,后端,java,stackoverflow

二.优先线上问题解决

记一次 stackoverflowerror 线上排查过程,【项目实战】,后端,java,stackoverflow

请原谅我抽象的画风

    temp 方案.首先的线上的稳定性肯定是第一要义,客户可不会等你长篇大论抓包,分析,debug.过了30min还不恢复,资本的大刀就要砍到你身上了.所以我们先想到的是代码回退,镜像回滚解决问题优先.虽然说是临时方案,那这时候我觉得这可能是最重要的最佳方案.毕竟老镜像是不会出任何问题的.

三.继续深入分析

    解决完线上的问题后,先从外层的堆栈打印来看,找到 ClassCastException 这里找到真实的原因,毕竟退下来的不仅仅是坏代码,还有需求迭代的正常需求还是需要继续推上去上线.

3.1 整体的流程梳理

记一次 stackoverflowerror 线上排查过程,【项目实战】,后端,java,stackoverflow

    找到报错第一步:

3.1.1 step1: classCastException

    先表象开始分析

记一次 stackoverflowerror 线上排查过程,【项目实战】,后端,java,stackoverflow
记一次 stackoverflowerror 线上排查过程,【项目实战】,后端,java,stackoverflow

从这里可以看到判断了是否为 Throwable 类型.如果是就进行 Exception 强转.这里就要复习一下了.

记一次 stackoverflowerror 线上排查过程,【项目实战】,后端,java,stackoverflow

StackOverFlowError 继承 Error ,ErrorThrowable 继承而来. Exception 则是另外的分支. 对于 ErrorException 也有通行的原则. Exception 一般是程序中用以来抛出程序异常所使用的且一般是能够通过编码优化来解决的,或是用来 try catch exception 来进行捕获处理的. Error 则是用来表达程序运行期间出现的严重错误,这时候通常是jvm级别的.如常见的OutOfMemoryError,stackOverFlowError.等.通常则是无法通过代码来进行捕获的.

    有了这些基础知识后,再回来这里虽然StackOverFlowErrorException都继承于 Throwable .但这是两个子的实现,没法做到强转.由之得到了 ClassCastException .后面这就是转成了 ClassCastException .这个类则是继承自 Exception .通过 try catch 捕获异常后,得到了正常的日志打印,也就是收到的日志告警. 然后这仅仅是表现.根因还没有找到.

    当然这段代码也需要进行优化.如果得到的是Error的类型就要对应的进行Error的处理而不是仅仅对Throwable都统一强转为Exception
代码优化

 Exception exception = null;
 f(ar instanceof Error){
      Error arError=(Error)ar; 
      exception=new Exception (arError);
 }else if(ar instanceof Exception){
      exception = (Exception) ar;
 }

3.1.2 step2:事情远没有结束,到底是哪里出问题 StackOverFlowError

    本质上还是由于StackOverFlowError才得到的如上的 ClassCastException. 回忆下 JVM 的内存布局(如下图)

记一次 stackoverflowerror 线上排查过程,【项目实战】,后端,java,stackoverflow

    能发生 StackOverFlowError 只有在线程私有的 stack(native method stack | virtual method stack) 这里.这里通常发生这个错误的原因是因为方法调度的深度过长了或是线程本身分别的内存太小不足以支持现在的复杂调用.

  • 第一种场景:常见的如递归调用.
  • 第二种场景: jvm 在1.5 之后默认的xss 大小默认为 1m.一般场景下支持1000-2000个深度调用没问题.包括递归.(没试过.数值参考自:深入理解java虚拟机)

3.1.3 找到问题对比代码

    从一般情况下第二种场景不太可能出现.还是回到递归调用引起的.排查代码.花不多少,看代码,通过对比版本之间diff(对比时间稍微有点长).简略如下:

无问题代码

private static void error(Logger logger, String message, Object... arg) {
        if (isLogOn(LogLevelEnum.ERROR, logger)) {
            if (arg != null && arg.length > 0 && arg[0] instanceof Throwable) {
                logger.error(message, arg[0]);
            } else {
                logger.error(message, arg);
            }

            TRACER_LOGGER.error(message, arg);
        }
    }
public static void error(Object... arg) {
        String message = getMessage("{}", 4, arg);
        error(getSoaErrorLogger(), message, arg);
    }

    public static void error(String message, Object... arg) {
        message = getMessage(message, 4, arg);
        error(getSoaErrorLogger(), message, arg);
    }

代码优化后的代码 有问题版

private static void error(Logger logger,String realMessage, String message, Object... arg) {
        if (isLogOn(LogLevelEnum.ERROR, logger)) {
            if (arg != null && arg.length > 0 && arg[0] instanceof Throwable) {
                logger.error(message, arg[0]);
            } else {
                logger.error(message, arg);
            }

            TRACER_LOGGER.error(message, arg);
        }
    }
public static void error(Object... arg) {
        String message = getMessage("{}", 4, arg);
        error(getSoaErrorLogger(), message, arg);
    }

    public static void error(String message, Object... arg) {
        message = getMessage(message, 4, arg);
        final String realMessage=message;
        error(getSoaErrorLogger(),realMessage, message, arg);
    }

代码优化后的代码 完善版

private static void error(Logger logger,String realMessage, String message, Object... arg) {
        if (isLogOn(LogLevelEnum.ERROR, logger)) {
            if (arg != null && arg.length > 0 && arg[0] instanceof Throwable) {
                logger.error(message, arg[0]);
            } else {
                logger.error(message, arg);
            }

            TRACER_LOGGER.error(message, arg);
        }
    }
public static void error(Object... arg) {
        String message = getMessage("{}", 4, arg);
        final String realMessage=message;
        error(getSoaErrorLogger(),realMessage, message, arg);
    }

    public static void error(String message, Object... arg) {
		final String realMessage=message;
        message = getMessage(message, 4, arg);        
        error(getSoaErrorLogger(),realMessage, message, arg);
    }

    咋一看没有任何问题.但是上线后出现第二个方法递归调用自身(但是第二个方法没有变更内容哈).本质上的原因就是因为修改第一个方法增加了入参.但是仅修改了第三个方法,第二个方法没有修改.没有出现编译问题.因为本身第二个方法是一个Object… arg的数组调用.好坑.

四.总结

  • 区别ErrorException.系统最外层建议捕获所有异常,也就是Throwable,但是具体是Error,还是Exception要进行区分处理.
  • 尽量不使用,少使用数组式使用.如String… args.Integer… args .即使要用,也尽量不要用Object… args .避免调用错误.
  • 在做技术优化时,尽可能评估影响,对线上抱有充分的敬畏.慎之又慎.如没有特别的收益,可不上线.上线也要保证每一行改动与本次受影响的代码做到测试
  • 修改代码找到所有find usage ,避免出现错改,漏改.可以利用自带IDE的工具 做到.
记一次 stackoverflowerror 线上排查过程,【项目实战】,后端,java,stackoverflow

赠人玫瑰 手有余香 我是柏修 一名持续更新的晚熟程序员
期待您的点赞,关注加收藏,加个关注不迷路,感谢
您的鼓励是我更新的最大动力
↓↓↓↓↓↓文章来源地址https://www.toymoban.com/news/detail-817731.html

到了这里,关于记一次 stackoverflowerror 线上排查过程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 记一次linux复制病毒处理过程

    某天我的阿里云突然发信息告诉我服务器有自变异木马,我用远程工具连接服务器异常卡顿甚至掉线,reboot也不好使.用阿里云的网页控制台会好些,但还是卡,我又用阿里云控制台重启服务器,重启之后发现服务器完全连不上了,ping也ping不通了,我问了客服说可以用救援连接试试,果

    2024年01月24日
    浏览(64)
  • 记一次后台开发面试拷打过程

    开头简单的自我介绍,面试官和我聊了聊天缓解个人紧张状况,然后就让开屏幕共享开视频做题目,做完以后,问了一些问题,就让等通知了,估计是凉了,不过这里且把当时做的笔试题目复盘一下吧!题目是ai做的题解,唉,AI都比我强,比我面试的时候解释的强多了,未来

    2024年02月08日
    浏览(44)
  • 记一次批量更新mysql数据过程

    一、前言 需求背景:mysql数据库中有一个表的数据(600多万)有一个字段的内容需要解密再通过另外一种加密方式进行加密再回存。通过java程序计算完成更新。 二、方案一 一条条计算更新。这里是将手机号解密,在通过另外一种方式回存。 算法步骤: 1、查询需要解密的数

    2024年02月10日
    浏览(36)
  • 记一次 Oracle 下的 SQL 优化过程

    事情是这样的,UAT 环境的测试小伙伴向我扔来一个小 bug,说是一个放大镜的查询很慢,转几分钟才出数据,我立马上开发环境试了一下,很快啊我说😏,放大镜的数据立马就出来了,然后我登录 UAT 环境一看,诶是有些慢😕 ,于是开始了我的排查之旅... 首先我立马拿到了

    2024年02月05日
    浏览(43)
  • 记一次docker服务启动失败解决过程

    环境:centos 7.6 报错:start request repeated too quickly for docker.service 由于服务器修复了内核漏洞,需要重启,没想到重启后,docker启动失败了 查看状态 如下图 里面有一行提示: 提示要 journalctl -x 这个命令查看详细问题,其实用这个命令无法定位到具体问题的,于是使用了另外一

    2024年01月18日
    浏览(78)
  • 记一次SpringBoot应用性能调优过程

    使用SpringBoot、MyBatis-Plus开发一个接口转发的能,将第三方接口注册到平台中,由平台对外提供统一的地址,平台转发时记录接口的转发日志信息。开发完成后使用Jmeter进行性能测试,使用100个线程、持续压测180秒,测试结果如下,每秒仅支持8个并发。 服务器 作用 CPU核数 内

    2024年02月03日
    浏览(45)
  • 记一次SVN信息泄露挖掘过程(附工具)

    SVN是源代码管理软工具。使用SVN管理本地代码过程中,将生成名为.svn的隐藏文件夹,包含非常重要的源码信息。当网站管理员在发布代码时,没有使用导出功能,直接进行复制粘贴,导致出现SVN信息泄露漏洞 常见漏洞变现为 :域名/.svn/entries。 使用的工具为:AWVS,SvnExploi

    2024年02月06日
    浏览(37)
  • 记一次Native memory leak排查过程

    路由计算服务是路由系统的核心服务,负责运单路由计划的计算以及实操与计划的匹配。在运维过程中,发现在长期不重启的情况下,有TP99缓慢爬坡的现象。此外,在每周例行调度的试算过程中,能明显看到内存的上涨。以下截图为这两个异常情况的监控。 TP99爬坡 内存爬坡

    2024年02月11日
    浏览(46)
  • 记一次 .NET某游戏后端API服务 CPU爆高分析

    前几天有位朋友找到我,说他们的API服务程序跑着跑着CPU满了降不下去,让我帮忙看下怎么回事,现在貌似民间只有我一个人专注dump分析,还是申明一下我dump分析是免费的,如果想学习.NET高级调试的分析技术,可以来我的训练营看看,话不多说,dump分析走起! 昨天录了一

    2024年03月21日
    浏览(43)
  • 记一次Elasticsearch GeoIpDownloader的启动异常排查过程

    最近碰到了Elasticsearch GeoIpDownloader相关的一个异常,花费了不少精力排查,故此记录一下,希望碰到同样问题的童鞋们少走弯路。 这个异常是在Elasticsearch启动的过程中报的error,如下所示,从提示信息来看是因为GeoIpDownloader更新数据库失败导致。 GeoIpDownloader是用于下载地图数

    2024年02月02日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包