专栏名称: ImportNew
伯乐在线旗下账号,专注Java技术分享,包括Java基础技术、进阶技能、架构设计和Java技术领域动态等。
目录
相关文章推荐
芋道源码  ·  好记性不如烂笔头:Spring(春天) ·  昨天  
芋道源码  ·  告警:MyBatis-Plus中慎用@Tra ... ·  2 天前  
Java编程精选  ·  CEO裁员后不理解:原来100个人干50个人 ... ·  3 天前  
51好读  ›  专栏  ›  ImportNew

公司来了个大佬,把 FullGC 40 次/天优化为 10 天 1 次,太秀了~!

ImportNew  · 公众号  · Java  · 2023-09-04 09:05

正文

请到「今天看啥」查看全文


基于前面的知识,于是进行了第一次的线上调优:提升新生代大小,将初始化堆内存设置为最大内存。

-Xmn350M -> -Xmn800M
-XX:SurvivorRatio=4 -> -XX:SurvivorRatio=8
-Xms1000m ->-Xms1800m

将 SurvivorRatio 修改为 8 的本意是想让垃圾在新生代时尽可能的多被回收掉。

就这样将配置部署到线上两台服务器(prod,prod2 另外两台不变方便对比)上后,运行了 5 天后,观察 GC 结果,YoungGC 减少了一半以上的次数,时间减少了 400s,但是 FullGC 的平均次数增加了 41 次。YoungGC 基本符合预期设想,但是这个 FullGC 就完全不行了。

就这样第一次优化宣告失败。

第二次优化

在优化的过程中,我们的主管发现了有个对象 T 在内存中有一万多个实例,而且这些实例占据了将近 20M 的内存。于是根据这个 bean 对象的使用,在项目中找到了原因:匿名内部类引用导致的,伪代码如下:

public void doSmthing(T t){
 redis.addListener(new Listener(){
  public void onTimeout(){
   if(t.success()){
    //执行操作
   }
  }
 });
}

由于 listener 在回调后不会进行释放,而且回调是个超时的操作,当某个事件超过了设定的时间(1 分钟)后才会进行回调,这样就导致了 T 这个对象始终无法回收,所以内存中会存在这么多对象实例。

通过上述的例子发现了存在内存泄漏后,首先对程序中的 error log 文件进行排查,首先先解决掉所有的 error 事件。然后再次发布后,GC 操作还是基本不变,虽然解决了一点内存泄漏问题,但是可以说明没有解决根本原因,服务器还是继续莫名的重启。

内存泄漏调查







请到「今天看啥」查看全文