log4j2:占位符引起的内存泄漏bug

  • log4j2使用
  • 调用现象
  • 排查手段
  • 耗时原因
  • 问题回顾

log4j2使用

之前用的logback,然后(抽了)换成log4j2,主要log4j2支持异步日志(基于disruptor),据说性能很高,但是用了后发现不少问题,记录下最近发现的一个严重bug

调用现象

访问接口的时间重复打印了两次日志,第一次是fegin返回日志,第二次是springmvc返回日志,但是发现耗时十几秒;

排查手段

1.开始时手段比较粗暴,直接观察日志打印时间前后时间差,发现耗时确实比较长,然后fegin直接进行了降级,于是把fegin返回日志禁掉,发现还是耗时将近10s。
2.然后监控线程和堆内存大小,这里用arthas监控的,发现新生代内存飙涨达到1g多(实际粘贴出来只有200k),线程cpu使用率达到100%,gc日志也频繁输出swt,如图(经过调整过还是百分之60%):


3.用jcmd pid JRF 记录器记录下一次请求的堆栈情况,然后导出服务器,用JProfiler(支持ssh在线attach)导入记录的备份文件:如图:


从这几张图已经明确log4j2的logger.info导致的,将日志输出改成debug或者去掉就没这问题,而StrSubstitutor.substitute已经接近递归调用了,该方法耗时将近6s.

耗时原因

输出的gc日志也没有内存溢出(堆溢出、栈溢出、堆外溢出)的错误,百思不得其接写法有哪里不对,只是最简单logger.info,
1.通过查到StrSubstitutor该类的是跟appache-text中的同名类差不多解决占位符问题的,在想也是loggger.info第一个参数有{}这种占位符也不影响吧,然后观察到输出的返回参数里带有${1},然后把带有${1}的字段去掉,结果耗时只有100ms,
然后再看源码果然有:

构造方法用的默认

默认替换${}中间的变量名

并且出现循环调用自己

源码里的该方法比较长,没有仔细琢磨下,但是本地debug了下,发现会将整个输出的字符串进行循环替换;,然后找到替换占位符的方法,

看到里面的替换占位符的方法:StrLookup,有如下实现类,

就点进各类去看了,有替换自定义的属性的,传入变量的,发现暂时不需要这些,然后跳到上级调用类MessagePatternConverter.format

发现该方法又一次进行循环判断,也同时看到有条件才可以进入,nolookup为true就不变遍历
然后看到常量配置类里这个默认是false,果断将log4j2.component.properties的log4j2.formatMsgNoLookups设置true(也可以在log4j2的logger初始化前设置System.setProperty).
2.该漏洞明显是字符串过长而导致递归调用的,每次递归和循环都是新建一个StringBuilder,还有递归曾经有两百多层,所有还可以将线程栈初始容量设置大点-X:xss,还有新生代设置大点,大对象进行gc限制也设置大点。当然这种办法可能耗时会减少,但是治标不治本,而且对硬件有要求。

问题回顾

1.定位问题用了观测线上堆栈与cpu情况、线下查看dump详情、和源码阅读三种方式。
2.该bug通过百度、google都没找到相似问题,github的log4j2项目的bug列表也没,目前升级到2.13.3问题依旧还在,小编英文不太好,所以就不提了,有github账号的朋友可以去提下(lo4j2的github地址)。

log4j2:占位符引起的内存泄漏bug相关推荐

  1. WPF框架的内存泄漏BUG

    用户在使用GIX4某模块的过程中,内存只见加不见减.我们怀疑出现了内存泄漏,所以我花了相当一段时间来进行此问题的排查. 我使用Red Gate公司的产品ANTS Memory Profiler 5进行 ...

  2. polkits存在内存泄漏现象

    服务器中polkits内存占用很大,经过查阅资料发现可能是polkits的内存泄漏导致,这个可以作为后续服务器内存分析的一个参考. polkits存在内存泄漏现象.​ 参考: Bug 29069 -  ...

  3. Android内存泄漏查找和解决

    Android内存泄漏查找和解决 目录: 内存泄漏的概念 一个内存泄漏的例子 Java中"失效"的private修饰符 回头看内存泄漏例子泄漏的重点 强引用与弱引用 解决内部类的内 ...

  4. java string 占位符_驳《阿里「Java开发手册」中的1个bug》?

    前两天写了一篇关于<阿里Java开发手册中的 1 个bug>的文章,评论区有点炸锅了,基本分为两派,支持老王的和质疑老王的. 首先来说,无论是那一方,我都真诚的感谢你们.特别是「二师兄」, ...

  5. 我的程序跑了60多小时,就是为了让你看一眼JDK的BUG导致的内存泄漏。

    从一个BUG说起 前段时间翻到了一个 JDK 有点意思的 BUG,带大家一起瞅瞅. https://bugs.java.com/bugdatabase/view_bug.do?bug_id=81371 ...

  6. 我的程序跑了 60 多小时,就是为了让你看一眼 JDK 的 BUG 导致的内存泄漏

    来源 | why技术 荒腔走板 大家好,我是 why,老规矩,先来一个简短的荒腔走板,给冰冷的技术文注入一丝色彩. 上面图片中这个正在奔跑的少年,是正在参加校运会的我,那一年我 18 岁,高三. 参加 ...

  7. java占位符填充_程序员:深入理解Java虚拟机,对象的内存布局

    在 HotSpot 虚拟机中,对象在内存中存储的布局分为 3 块区域:对象头 ( Header ) .实例数据 ( InstanceData ) 和对齐填充 (Padding) . 一.对象的内存布局 ...

  8. 无处不在的内存泄漏-苹果BUG?

    即使你对自己的技术功底有再多的自信,都请养成使用Instruments工具排查内存泄漏的良好习惯, 即使Instruments再牛逼,你也还要养成看接口文档的良好习惯,因为你防谁也防不了苹果... 下 ...

  9. 修复miniblink一处内存泄漏的bug

    最后的结论很简单,是我绑定v8 function的时候没释放.但查找问题的过程比较艰难,因为 v8的代码实在太难读了. 下面先大概了解下v8的垃圾回收机制. v8\src\global-handles ...

最新文章

  1. php自动轮播图代码,JavaScript如何实现动态轮播图效果?(代码示例)
  2. SAP MM MB1C + 523 移动类型的使用
  3. 低压差降压稳压电路设计
  4. container_of分析
  5. 【IT资讯】TIOBE - 2020年8月编程语言排行
  6. 计算机网络spoc作业4
  7. 提取数据_EasyStat如何提取数据+个性化出图
  8. msdn安装后怎么用_Win10不好用?安装官方版精简Win10后,运行比win7更快更流畅
  9. 锐起无盘服务器改dns,锐起无盘多配置教程-菜鸟版(老鸟飘过)
  10. 双显示器 启动黑屏 黑苹果_教你注入EDID 解决黑苹果显示器显示问题
  11. 用python实现闯越顶岗实习签到
  12. 关于elementplus 的:suffix-icon=“Search不显示问题记录
  13. 前端追梦人CSS教程
  14. 窥尽大数据背后被遮掩起来的财富
  15. 需要小程序源码/模板的进
  16. 这样print才够劲!
  17. OpenCV4学习笔记(55)——基于KNN最近邻算法实现鼠标手写数字识别
  18. c3p0-config.xml配置文件的那些事
  19. ArcGis For JavaScript API Drawing Tool (绘图工具又称框选地图)
  20. 家庭主夫怎么在今年3月27号的市场中利用金叉死叉进行波段操作

热门文章

  1. 致大学计算机老师的一封信,优秀书信作文:致大学老师的一封信
  2. 专业的个人记帐软件 爱上记帐 1.0.1
  3. 创业公司的产品经理应该怎么去做?
  4. 计算机音乐谱大全好汉歌,好汉歌民谣简谱
  5. FAIL : No keyword with name '/dev/mapper/vg1-lv1' found.(解决方法)
  6. 糖果将推翻译手机php切,全球首款翻译手机糖果S20发布 或将终结翻译机
  7. taobao.trade.fullinfo.get( 获取单笔交易的详细信息API接口),淘宝店铺订单明文接口代码分享
  8. 天池- IJCAI-18 阿里妈妈搜索广告转化预测新手入门经历(一:数据预处理、特征工程)
  9. ProM开发指北3——ProM插件开发入门
  10. matlab(二)统计图