范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

记一次内存泄漏引发的生产事故

  #头条创作挑战赛#概述
  本篇文章主要记录在生产环境上发生了内存泄漏导致系统OOM,造成了严重的后果,以致于本人吃土一个月,5555~本文主要对该问题做一个复盘,同时分析下什么是内存泄漏,如何识别你的系统中存在潜在可能的内存泄漏风险,并且哪些常见的场景可能会引发内存泄漏,需要引起我们特别注意。事件回顾事故背景
  某商业银行项目上部署了我们的风控系统,其中一个节点挂了,同时报了OOM的错误,还好其他节点正常work,不然本人要吃土一整年了,第二天本人就被要求出差到现场分析解决该问题。事故排查和修复
  通过dump生成的堆信息,用jprofiler(后面专门出文章介绍使用)工具发现:
  上面这个字符串对象特别多,几十万个,占用了大量的堆空间,根据这个字符串查询,发现是其他同事的代码中监控项使用不当导致。
  代码
  原因分析
  监控项的tag值要求是可枚举的,不能生成的每条tag都是唯一的,这样应用不会覆盖,而是保留每一条数据,导致内存爆炸。
  而这里的succList,是一个Set对象,虽然列表数量是确定的,但是每次请求过来顺序不一致,比如succList有10个对象,那么就会有10!种可能,最终撑爆内存。
  修复方案
  遍历succList, tag使用单条数据, 而不是把整个对象列表放进去,重新上线后监测,没有出现问题。
  小结
  因为监控项使用不当导致内存泄漏,最终导致OOM。其实内部复盘了下,主要开发人员对监控项不大会使用,对里面的底层原理也不甚了解,所以了解一个技术的底层实现还是非常重要的。而且,团队内部也缺少代码review,缺少生产级别数据的验证,一系列原因,最终导致出现该生产问题。什么是内存泄漏
  通俗的来说,内存泄漏就是占着茅坑不拉屎,你认为该对象用不上了,但是实际上还被程序使用,GC又无法回收,这种情况就是内存泄漏。
  如何对象判断是否还在被程序使用呢?
  GC的可达性分析算法来判断对象是否是不再使用的对象,本质都是判断一个对象是否还被引用。那么对于这种情况下,由于代码的实现不同就会出现很多种内存泄漏问题(让JVM误以为此对象还在引用中,无法回收,造成内存泄漏)。
  内存泄漏和内存溢出
  内存泄漏(Memory Leak)最终的后果会导致内存溢出(Out Of Memory),但是内存溢出并不完全是内存泄漏导致,也有可能分配了一个大对象,数据库未分页查全量的数据等等。如何发现存在内存泄漏
  更关键的是我们应该如何提前发现我们的系统存在潜在的内存泄漏风险,从而规避生产出现OOM问题?测试环境模拟测试,开启GC日志输出到文件里通过GC Easy工具分析日志,观察下每次垃圾回收后,它的内存使用情况如果发现回收完后,堆占用是递增的趋势,那么很有可能有内存泄漏的问题。
  此外,大家还可以使用Eclipse Memory Analyzer、JProbe Profiler、JVisualVM 等工具分析程序的内存信息,凭借个人经验判断是否有内存泄漏问题(说了个寂寞,哈哈哈~~)。内存泄漏的几种常见场景
  下面通过几个案例带大家了解下常见的几种内存泄漏的场景,如果大家的程序中有类似的场景,那么就要特别注意了。静态字段
  可能导致潜在内存泄漏的第一种情况是大量使用静态变量。在Java中,静态字段的生命周期通常与应用程序一样。
  简单而言,长生命周期的对象持有短生命周期对象的引用,尽管短生命周期的对象不再使用,但是因为长生命周期对象持有它的引用而导致不能被回收。public class MemoryLeak {     static List list = new ArrayList();     public void oomTests(){         Object obj new Object();//局部变量         list.add(obj);     } } 复制代码
  如何避免:最大限度地减少静态变量的使用使用单例时,依赖于延迟加载对象而不是急切加载的实现未关闭的连接池资源
  在对数据库进行操作的过程中,首先需要建立与数据库的连接,当不再使用时,需要调用close方法来释放与数据库的连接。只有连接被关闭后,垃圾回收器才会回收对应的对象。否则,如果在访问数据库的过程中,对Connection、Statement或ResultSet不显性地关闭,将会造成大量的对象无法被回收,从而引起内存泄漏。public static void main(String[] args) {     try{         Connection conn =null;         Class.forName("com.mysql.jdbc.Driver");         conn =DriverManager.getConnection("url","","");         Statement stmt =conn.createStatement();         ResultSet rs =stmt.executeQuery("....");     } catch(Exception e){//异常日志     } finally {         // 1.关闭结果集 Statement         // 2.关闭声明的对象 ResultSet         // 3.关闭连接 Connection     } } 复制代码
  如何避免:始终使用finally块来关闭资源可以用sonar等工具检查代码改变哈希值
  改变哈希值,当一个对象被存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段了。
  否则,对象修改后的哈希值与最初存储进HashSet集合中时的哈希值就不同了,在这种情况下,即使在contains方法使用该对象的当前引用作为的参数去HashSet集合中检索对象,也将返回找不到对象的结果,这也会导致无法从HashSet集合中单独删除当前对象,造成内存泄漏。
  这也是 String 为什么被设置成了不可变类型,我们可以放心地把 String 存入 HashSet,或者把String 当做 HashMap 的 key 值;
  当我们想把自己定义的类保存到散列表的时候,需要保证对象的 hashCode 不可变。public class ChangeHashCode1 {     public static void main(String[] args) {         HashSet hs = new HashSet();         Point cc = new Point();         cc.setX(10);//hashCode = 41         hs.add(cc);          cc.setX(20);//hashCode = 51  此行为导致了内存的泄漏          System.out.println("hs.remove = " + hs.remove(cc));//false         hs.add(cc);         System.out.println("hs.size = " + hs.size());//size = 2          System.out.println(hs);     }  }  class Point {     int x;      public int getX() {         return x;     }      public void setX(int x) {         this.x = x;     }      @Override     public int hashCode() {         final int prime = 31;         int result = 1;         result = prime * result + x;         return result;     }      @Override     public boolean equals(Object obj) {         if (this == obj) return true;         if (obj == null) return false;         if (getClass() != obj.getClass()) return false;         Point other = (Point) obj;         if (x != other.x) return false;         return true;     }      @Override     public String toString() {         return "Point{" +                 "x=" + x +                 "}";     } } 复制代码
  如何避免:自己写的对象要重写hashCode和equals方法对象被加入到HashSet、HashMap等容器后,尽量避免修改。引用外类的内部类
  默认情况下,每个非静态内部类都包含对其外部类的隐式引用。如果我们在应用程序中使用这个内部类对象,那么即使在我们的外部类对象不再使用了,它也不会被垃圾收集。因为内部类对象隐式地保存对外部类对象的引用,从而使其成为垃圾收集的无效候选者。在匿名类的情况下也是如此。
  如何避免如果内部类不需要访问当前包含这个内部类的父类的成员时,请考虑将其转换为静态类
  ThreadLocal使用不当
  ThreadLocal使我们能够将状态隔离到特定线程,从而允许我们实现线程安全。
  一旦保持线程不再存在,ThreadLocals应该被垃圾收集。是当ThreadLocals与现代应用程序服务器一起使用时,问题就出现了。现代应用程序服务器使用线程池来处理请求而不是创建新请求(例如 ,在Apache Tomcat的情况下为Executor)。此外,他们还使用单独的类加载器。由于 应用程序服务器中的线程池在线程重用的概念上工作,因此它们永远不会被垃圾收集 - 相反,它们会被重用来处理另一个请求。现在,如果任何类创建 ThreadLocal 变量但未显式删除它,则即使在Web应用程序停止后,该对象的副本仍将保留在工作线程中,从而防止对象被垃圾回收。
  如何避免最好手动调用ThreadLocal.remove()方法删除当前线程值,代码如下:try {     threadLocal.set(System.nanoTime());     //... further processing } finally {     threadLocal.remove(); } 复制代码finalize()方法
  finalize是潜在的内存泄漏问题的另一个来源。每当重写类的 finalize()方法时,该类的对象不会立即被垃圾收集。相反,GC将它们排队等待最终确定,在稍后的时间点才会发送GC。
  如果用finalize()方法编写的代码不是最佳的,并且finalize队列无法跟上Java垃圾收集器,那么迟早,我们的应用程序注定要遇到 OutOfMemoryError。
  如何避免我们应该总是避免使用finalize方法总结
  本文主要分享了自己项目中遇到的一个内存泄漏的问题,然后引出了内存泄漏的几种常见场景,希望大家能够引起重视。

HTTP协议演变为什么QUIC是顺应大势?大家好,很高兴又见面了,我是高级前端进阶,由我带着大家一起关注前端前沿深入前端底层技术,大家一起进步,也欢迎大家关注点赞收藏转发!高级前端进阶1。HTTP1。0面临的问题HTTP1林孝埈重返韩国,胸前佩戴五星红旗!韩网友集体抵制该禁止入境林孝埈,前韩国奥运冠军,如今已经是中国人,代表中国队参赛了。现在,林孝埈回到韩国,引发韩国媒体和网友的热议。3月10日至12日,2023年短道速滑世锦赛将在韩国首尔举行,中国队已经老挝小众线路西北部自驾探秘之旅,难得的净土,原始淳朴!贫穷神秘信仰原始淳朴,是老挝旅行的关键词。提起老挝,除了大家熟悉的琅勃拉邦和万象,其实老挝西北部这条容易被游客忽略的小众路线,是难得的净土,很值得深度探索。东南亚的老挝,作为一个超Ins创始人再造美版拳打推特,脚踢TikTok?文何伊然编辑王芳洁Instagram创业二人组回来了。2023年2月,一款名叫Artifact的新闻类软件在美国应用商店悄然上线,平台幕后操盘手正是In5199元的荣耀Magic5Pro,值不值得买?现场看完荣耀发布会,大概总结下来就有几个卖点,主要是针对Magic5Pro的评价显示神器褪黑素扫码神器10度可扫信号神器电话稳定续航神器硅碳聚能环未来神器一个眼神你懂的荣耀Magi新一任董事长任职资格获批,曹卫东履新中原信托大河财立方记者陈玉静年内第四家信托公司董事长发生变更。3月6日,中原信托有限公司(以下简称中原信托)官网发布关于董事长资格获批变更法定代表人的公告(以下简称为公告)。公告显示,经董2023年3月6日钾肥行情钾肥氯化钾钾肥市场价格仍呈现弱势下行的状态,业内人士心态仍不看好,手中的货源多在低价抛售,市场价格持续走低。目前港口进口钾约旦以色列白钾价格多在35003600元吨,南方价格较高,陈剑县域经济基本数据关于县域经济研究探讨(一)今年3月21日至23日在海口举办的中国县域经济发展大会,吸引了诸多朋友的关注。很多朋友的问题是,为什么要关注县域经济,县域经济涉及到哪些内容呢?笔者给出的回答是,县域经济涉及到的内百年投行瑞信遭长期股东清仓,被指未来不确定瑞信(CreditSuisse)视觉中国资料图百年投行瑞士信贷集团(CreditSuisse,下称瑞信)持股时间最长的股东之一,已出售了其在这家银行的全部股份。当地时间3月5日,美氮化镓继金属锂后,又一个投资领域的新宠在金融投资领域,投资者的首要目标是获得高额回报,而高风险高回报的投资领域才是他们最主要的选择。其中投资科技和新兴产业是很多投资者关注的方向。其中,氮化镓被认为是未来科技领域的一个新问政中国稳增长关键之年扩内需应该怎么干?今年的政府工作报告中,着力扩大国内需求被排在八大任务之首。而去年底召开的中央经济工作会议,也把着力扩大国内需求作为2023年经济工作的首要任务。那么,在畅通内循环的过程中,该怎么打
柠檬能杀死癌症,比化疗强一万倍吗?喝柠檬水能不能抗癌?望知晓说起柠檬,大家可能嘴里就会流酸水,柠檬不仅味道清香,其中富含的维生素C柠檬酸和柠檬烯等营养成分,具有抗氧化和辅助降压的效果,称得上是是水果中的保健品。有相关报道称,长期食用柠檬能够肾精不足早有信号,出现这6个症状,要注意补肾调理了提起男性的功能问题,就少不了提到肾虚,肾亏的词汇,而其中大部分都是指的肾精亏虚。肾精,顾名思义是肾里面的精华,是我们人体最重要的基础物质之一。虽然看不见,摸不到,但是身体不能少,当阴阳两虚?两味中药,一个补阳之最,一个补阴之最,阴阳同调怕冷是阳虚,怕热是阴虚,那既怕冷,又怕热呢?是阴阳两虚。那么我们又该如何调理阴阳呢?要想调理阴阳两虚,首先要搞清阴虚与阳虚的主要表现,阳虚就是指体内阳气不足了。阳气对人体具有温煦推体虚多病阴阳两虚?送你四味中药,阴阳双补肝肾同治文章的开头,请大家回忆一下,小时候,在学生时代,身边是否总有几个人身子骨弱,平日里老爱生病,三天一小假,两周一大假的。不过,自从参加工作以后,请病假的人倒是越来越少了,大家要不是真献给伊的三行诗文小草(原创)我向往的爱情(第71节)你看见天上月吗,圆圆的月如你的笑脸,玉钩月如你弯弯的眉月的心思,是一坛万年老酒,月华的酒香,从天上飘向凡间月高高在天,我只是大地的一粒微尘,遥男人过了六十岁,还找女人,大多原因有三百年孤独说幸福晚年的秘诀不是别的,而是与孤独的体面约定。人啊,日子总是一个人的日子,生活也总是一个人的生活,我们终要见过所有的世态人情,然后明白什么是冷暖自知。尤其是到了老年的时候金秋诗画(293期)一清一浊道不同1教师节作者姜保坤三尺讲台看世风,一清一浊品花红。有为全在无为处,师己师人道不同。师己师人道不同,甘为桃李抱春风。听蝉劝客枫林下,一缕斜阳似火红。2古风白莲作者刘平礼素面莲花心里苦夜读把握人生之尺,不为丈量他人,只为修正自己从此心宽似海。为人处世,有些尺子,要放有些尺子,要收。有收起尺子的智慧,才能不为其所困,过张弛自如的人生。收起经验之尺每个人的人生之路,都需要靠自己去走。体会这种东西,同样只有在自豫法品读丨你的坚持,终将美好朗读者延津县法院徐冰晶回望过去的一年,我们收获过欣喜过,也跌倒过迷茫过,但我们一直在往前走,不停留。无论顺风顺水也好,逆水行舟也罢,请相信,你的坚持,终将美好。又到岁末,这些话,送举世皆修,人生即是修行,修心人生即是修行,修心稻盛和夫心曾说人生即是修行,修心。王阳明心学曾说知行合一。心学活着,我们要修行要修行,先修心心在尘世所染,欲挣脱修佛心心在尘世所绊,欲逍遥修道心心在尘世所思,欲统女孩天生平胸是一种怎样的体验?漫画解析,看完谁破防了俗话说,爱美之心人皆有之,女性朋友对于美丽的追求从未停止,无论是过去还是现在大多数女性都是非常爱美的。只是随着时代的变化,人们对于美丽的追求也有了很大的变化,可能在过去的时候,很多