记一次排查线上OOM详细过程和解决思路

news2025/1/31 19:53:26

文章目录

  • OOM起因
  • 排查过程

OOM起因

前言声明:本人菜鸟一枚,如有地方描述不当望谅解,毕竟本人身处某十八线小城市三十六线小公司。

国庆节前头给项目换了套参数加解密方式,换完之后服务时不时就会出现如下报错,服务停止:

HikariPool-1 - Thread starvation or clock leap detected (housekeeper delta=1m11s757ms601µs134ns)

翻译后是HikariPool-1-检测到线程不足或时钟跳跃。

搜索了很多文章以为是HikariPool数据库连接池配置不合理导致的,但一番排查后并非该问题,直至后来看见一个清晰的错误,没错那就是OOM(OutOfMemoryError: Java heap space),堆内存溢出了,可惜头并未借由此机会让我去检查,而是选择了重启服务。

头质问我是不是在程序中写了死循环或者大量创建对象的情况。

怎么可能,写代码如此不规范的我是不可能在程序中如此乱搞的,而且在换加解密之前程序是如此健壮,测试做完压测后也并未出现OOM。而在换完加解密方式后,测试发很小的请求就出现了上边线程不足的情况。

后续头让修改启动参数,增大堆内存,也并未有所好转。

正值头要外出培训三天,因此给了我一个千载难逢的好机会。第一天他就让我走查一遍所有代码,不合适的地方全部都改掉。

我心里冷哼一声,就这?我心里还是很大程序怀疑加解密有问题的。

翻来覆去决定查看日志,也并未发现是哪块代码导致的。这就有些为难我月某人了,出此下策我决定:Arthas,启动!

通过Arthas提供的监控面板,我频繁的疯狂触发接口,从监控上不难看到我们的老年代不出意外的越来越大辣!(这里只复原并提供模拟,就不暴露项目内容了)。

在这里插入图片描述
通过面板可以发现频繁的触发了FULL GC,但是老年代还是居高不下,最终导致程序卡死,堆内存溢出~。

排查过程

想要解决问题,就要想办法复现,这样才能对症下药。我在复现时通过dashboard面板发现有多条线程去GC,最终因不能回收老年代内存导致不断调用线程去GC,因此才会报Thread starvation or clock leap detected介个错误。

由于在启动命令中并未指定垃圾收集器,且GC时并行调用线程,所以不出意外现在咱们的垃圾回收器应该是Parallel了。很好,也算是有了个解决思路,因此在查阅多篇资料后我决定换垃圾收集器来try一try。直接更换为了G1收集器

换完G1后,还是老问题,老年代的内存得不到释放,在查阅资料痛定思痛决定通过visualVM分析堆转储文件分析到底是哪里创建了回收不了的对象(肯定还是在加解密这块)。

通过jmap命令生成hprof文件,并拷贝到本地,使用JDK自带的VisualVM工具打开(以下仅供模拟,实际作者在生产中拿到的hprof文件中LinkedHashMap拥有千万个实例):

在这里插入图片描述

通过分析实例的垃圾回收根节点也是找到了罪魁祸首:

在这里插入图片描述

最终发现是工具类中使用了BouncyCastleProvider这个类,在每次加解密时,都创建该对象:

    /**
     * 加密
     *
     * @param content    加密的字符串
     * @param encryptKey key值
     */
    public static String encrypt(String content, String encryptKey) throws Exception {
        //设置Cipher对象
        Cipher cipher = Cipher.getInstance(ALGORITHMS, new BouncyCastleProvider());
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), KEY_ALGORITHM));

        //调用doFinal
        byte[] b = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));

        // 转base64
        return Base64.encodeBase64String(b);

    }

    /**
     * 解密
     *
     * @param encryptStr 解密的字符串
     * @param decryptKey 解密的key值
     */
    public static String decrypt(String encryptStr, String decryptKey) throws Exception {
        //base64格式的key字符串转byte
        byte[] decodeBase64 = Base64.decodeBase64(encryptStr);

        //设置Cipher对象
        Cipher cipher = Cipher.getInstance(ALGORITHMS, new BouncyCastleProvider());
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), KEY_ALGORITHM));

        //调用doFinal解密
        byte[] decryptBytes = cipher.doFinal(decodeBase64);
        return new String(decryptBytes);
    }

阅读了该类的源码后(部分):

public final class BouncyCastleProvider extends Provider
    implements ConfigurableProvider
{
    private static final Map keyInfoConverters = new HashMap();

    public void addKeyInfoConverter(ASN1ObjectIdentifier oid, AsymmetricKeyInfoConverter keyInfoConverter)
    {
        synchronized (keyInfoConverters)
        {
            keyInfoConverters.put(oid, keyInfoConverter);
        }
    }

    private void loadPQCKeys()
    {
        addKeyInfoConverter(PQCObjectIdentifiers.sphincs256, new Sphincs256KeyFactorySpi());
        addKeyInfoConverter(PQCObjectIdentifiers.newHope, new NHKeyFactorySpi());
        addKeyInfoConverter(PQCObjectIdentifiers.xmss, new XMSSKeyFactorySpi());
        addKeyInfoConverter(IsaraObjectIdentifiers.id_alg_xmss, new XMSSKeyFactorySpi());
        addKeyInfoConverter(PQCObjectIdentifiers.xmss_mt, new XMSSMTKeyFactorySpi());
        addKeyInfoConverter(IsaraObjectIdentifiers.id_alg_xmssmt, new XMSSMTKeyFactorySpi());
        addKeyInfoConverter(PQCObjectIdentifiers.mcEliece, new McElieceKeyFactorySpi());
        addKeyInfoConverter(PQCObjectIdentifiers.mcElieceCca2, new McElieceCCA2KeyFactorySpi());
        addKeyInfoConverter(PQCObjectIdentifiers.rainbow, new RainbowKeyFactorySpi());
        addKeyInfoConverter(PQCObjectIdentifiers.qTESLA_p_I, new QTESLAKeyFactorySpi());
        addKeyInfoConverter(PQCObjectIdentifiers.qTESLA_p_III, new QTESLAKeyFactorySpi());
        addKeyInfoConverter(PKCSObjectIdentifiers.id_alg_hss_lms_hashsig, new LMSKeyFactorySpi());
    }
    
    private static AsymmetricKeyInfoConverter getAsymmetricKeyInfoConverter(ASN1ObjectIdentifier algorithm)
    {
        synchronized (keyInfoConverters)
        {
            return (AsymmetricKeyInfoConverter)keyInfoConverters.get(algorithm);
        }
    }
}

所以只需在外部创建对象时保持单例或者说是保持只有一个实例即可,我在这里直接在外部创建了一个静态变量,用于解决这个问题。解决完再未出现老年代不释放内存的问题,如此,便大功告成了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1094034.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

rk3568 RT-LINUX 测试

G5501 产品详情 主线Linux是软实时系统,加入实时补丁后将其改造为硬实时系统。RT-LINUX 特点如下: 可抢占性 实现实时内核很重要的特点是可抢占性,就绪的高优先级的任务能够抢占低优先级任务。 进程调度策略 Linux内核支持实时进程和非实…

Java-lambda表达式与流处理

文章目录 一、lambda表达式二、方法引用三、Stream流 一、lambda表达式 在Java中,Lambda表达式是一种函数式编程的特性,它允许以简洁的语法编写函数或操作,而无需显式创建匿名类。Lambda表达式在Java 8中引入,是使Java更适应现代编…

RabbitMQ从0到1完整学习笔记一:《基础篇》

目录 启篇 一、初识MQ 1.1 同步调用 1.2异步调用 1.3 技术选型 二、RabbitMQ 架构 2.2 收发消息 2.2.1 交换机 2.2.2 队列 2.2.3 绑定关系 2.2.4 发送消息 2.3 数据隔离 2.3.1 用户管理 2.3.2 virtual host 三、SpringAMQP 3.1 案例入门 3.1.1 导入依赖 3.1.2 消息发送 3.1.2 消…

IIS 部署.NetCore,最细步骤

服务器安装环境 将.net core程序部署到IIS总体需要经过以下3个大步骤&#xff0c;其中在IIS上配置网站有些比较繁琐&#xff0c;我都会逐一给出详细步骤。 <1>安装IIS和.NetCORE运行时程序 <2>以文件的形式发布.NETCORE程序到指定目录 <3>IIS上面建立网站…

【BiLSTM-Adaboost预测】基于双向长短期记忆网络的Adaboost时间序列预测研究(matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

【LeetCode: 137. 只出现一次的数字 II | 位运算 | 哈希表】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

综述:大规模小目标检测

论文地址: Towards Large-Scale Small Object Detection: Survey and Benchmarks​arxiv.org/abs/2207.14096 目录 摘要 1.Introduction 1.1 与之前综述的比较 1.2 总结 2.小目标检测回顾 2.1 问题定义 2.2 主要挑战 2.3 小目标检测算法回顾 3.小目标检测的数据集 …

java网上商城购物网站管理系统69bz5 用户 会员springboot+vue

主要目的是通过网络平台方便商家进行商品订单管理并让客户有更好的购物体验。以商家在后端提供商品供客户在前端商城选购&#xff0c;客户将所需的商品加入购物车&#xff0c;然后通过结算购物车功能填写相应信息生成订单&#xff0c;付款以后再由商家在后端接收到订单进行处理…

自动驾驶中的数据安全和隐私

自动驾驶技术的发展已经改变了我们的出行方式&#xff0c;但伴随着这项技术的普及&#xff0c;数据安全和隐私问题也变得愈发重要。本文将探讨自动驾驶中的数据收集、数据隐私和安全挑战&#xff0c;以及如何保护自动驾驶系统的数据。 自动驾驶中的数据收集 在自动驾驶技术中…

深入理解 JVM(重点:双亲委派模型 + 垃圾回收算法)

一、什么是 JVM&#xff1f; JVM 是 Java Virtual Machine 的简称&#xff0c;意为 Java虚拟机。虚拟机是指通过软件模拟的具有完整硬件功能的、运行在一个完全隔离的环境中的完整计算机系统。可以认为 JVM 是一台被定制过的现实当中不存在的计算机&#xff0c;Java程序最终是…

Tuxera NTFS for Mac2024最新中文版本下载

如果你想用U盘在Mac和其他设备之间传输文件&#xff0c;可能会遇到一些问题。因为Mac系统支持的U盘格式和其他系统不同&#xff0c;而且苹果电脑对U盘的读写权限也有一定的限制。那么&#xff0c;Mac系统支持什么格式的U盘呢&#xff1f;苹果电脑读写权限怎么开启呢&#xff1f…

前端打包项目上线-nginx

第一步&#xff1a;下载nginx。 直接下载 nginx/Windows-1.25.2 pgp 第二步&#xff1a;解压zip包 第三步&#xff1a;打开文件夹&#xff0c;把http里的路径打开cmd 第四步&#xff1a;打开你的http-server服务&#xff0c;没有下载去下一次就ok了 打开后就可以访问了 第五步…

黑豹程序员-页面录音-在vue页面中进行录音wav/mp3

功能 在vue页面中进行录音wav/mp3 效果图 官网展示页面 https://recorder.zhuyuntao.cn/ 安装组件 npm i js-audio-recorder 测试页面 <template><h3>录音时长&#xff1a;{{ recorder.duration.toFixed(4) }}</h3><el-row><el-button type…

QE01/QA11/QA02屏幕增强

1、业务需求 需要对来料检验增加“合格数量”和“不合格数量”字段&#xff0c;涉及三个增强开发 2、QE01\QE02\QE03\QE51N屏幕增强 增强表 增强点BADI&#xff1a;QEEM_SUBSCREEN_5000 创建程序&#xff0c;包含子屏幕&#xff0c;在增强点中调用 在程序屏幕中绘制字段 在输…

【CNN-GRU预测】基于卷积神经网络-门控循环单元的单维时间序列预测研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Redux 错误处理

Redux 错误处理 这两天正好收尾一个 Redux 页面的重构&#xff0c;碰到了一些错误处理的方式&#xff0c;这里就写个笔记总结一下碰到的问题和几种处理方式 大体上是分为同步函数和异步函数两个方面去处理 同步函数 这个是指的是直接在 reducer 中进行操作&#xff0c;可以…

基于springboot实现医疗服务系统项目【项目源码+论文说明】计算机毕业设计

摘要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 医疗服务系统&#xff0c;主要的模块包括查看管理员&#xff1b;首页、个人中心、普通村民管理、乡村医生管理、公告信息管理、乡村诊室管理、…

抖音店铺提供优质服务|成都瀚网科技

抖音是中国领先的电子商务平台。为了帮助商家增加销量和品牌曝光度&#xff0c;抖音推出了精选联盟计划。精选联盟是由优质商家组成的联盟&#xff0c;旨在为消费者提供更多优质、高性价比的产品选择。那么&#xff0c;如何使用抖店开通精选联盟呢&#xff1f;这将在下面详细描…

计算机中了360后缀勒索病毒怎么办?360勒索病毒解密数据恢复

最近一段时间360后缀勒索病毒变得异常嚣张&#xff0c;时不时就会攻击企业的计算机服务器&#xff0c;导致众多的企业服务器被360后缀勒索病毒攻击。360后缀的勒索病毒并非360公司&#xff0c;是黑客专门具有针对性地研发的勒索病毒&#xff0c;通过加密企业的计算机给企业带来…

Docker容器与虚拟化技术:DaoCloud账户注册

目录 一、实验 1.DaoCloud 一、实验 1.DaoCloud &#xff08;1&#xff09;概念 DaoCloud是企业级容器云平台&#xff0c;它提供了一套容器集群解决方案&#xff0c;Daocloud可以管理你的计算资源&#xff0c;包括物理机和公有云环境&#xff0c;你可以在DaoCloud平台上部…