当前位置: 首页 > news >正文

一次惊心动魄的线上事故:记一次内存泄漏Bug的排查与解决全过程

前言

大家好,今天想和大家分享一个我接手外包项目时遇到的严重性能问题。这个问题排查过程异常曲折,整整花了3天时间才定位到根本原因。通过这次经历,我对OkHttp的连接池机制有了更深刻的理解,也意识到代码规范的重要性。

问题背景

我们接手了一个外包团队开发的直播类App,接手后测试发现一个奇怪的问题:只有华为手机在使用某个直播页面时会出现OOM(Out Of Memory)错误,其他品牌手机完全正常。

最初我们错误地认为这是华为机型的适配问题,但深入分析后发现问题的根源完全不同。

问题现象

  1. 机型差异:只有华为手机出现OOM,其他品牌手机正常
  2. 偶发性:问题不是必现,需要反复打开关闭直播页面多次才会触发
  3. 内存异常:OOM错误堆栈显示线程创建失败,暗示线程数过多

错误日志大致如下:

java.lang.OutOfMemoryError: pthread_create (1040KB stack) failed: Out of memoryat java.lang.Thread.nativeCreate(Native Method)at java.lang.Thread.start(Thread.java:733)at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:975)at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1393)...

排查过程

第一步:初步分析

看到OOM错误,我们首先想到的是内存泄漏,于是集成了LeakCanary进行监控,但没有发现明显的内存泄漏报告。这让我们意识到问题可能不是传统的内存泄漏。

第二步:使用Android Studio Profiler

我们使用AS Profiler监控应用运行状态,发现了一个惊人的现象:

每次打开直播页面,线程数量都会显著增加,而且在页面关闭后线程并没有被回收。反复操作几次后,线程数从正常的几十个增长到300多个,最终导致OOM。

第三步:分析页面代码

我们仔细分析直播页面的代码,发现页面中确实有很多网络请求,但奇怪的是其他页面也有网络请求,为什么只有这个页面有问题?

通过分析发现:

  1. 该页面确实比其他页面请求的接口多
  2. 反复打开页面时,线程数持续增长
  3. 页面关闭时,网络请求没有被正确取消

第四步:检查网络请求框架

项目使用的是Retrofit + OkHttp的经典组合。我们发现Retrofit确实是单例的,但问题出在OkHttpClient上。

通过断点调试,我们发现了一个严重问题:

虽然Retrofit是单例,但每次网络请求时都创建了新的OkHttpClient实例,导致连接池配置失效!

问题代码如下:

// 外包团队的错误实现
public class ApiManager {private static volatile Retrofit retrofit;public static ApiService getApiService() {if (retrofit == null) {synchronized (ApiManager.class) {if (retrofit == null) {retrofit = new Retrofit.Builder().baseUrl(BASE_URL).
http://www.xdnf.cn/news/1438759.html

相关文章:

  • 从一道面试题开始:如何让同时启动的线程按顺序执行?
  • Bug排查日记:从发现到解决的完整记录
  • 在word中使用lateX公式的方法
  • 力扣115:不同的子序列
  • Unity Android 文件的读写
  • Delphi 5 中操作 Word 表格时禁用鼠标交互
  • 更新远程分支 git fetch
  • 揭开PCB隐形杀手:超周期报废的技术真相
  • AI编码生产力翻倍:你必须掌握的沟通、流程、工具与安全心法
  • 一键掌握服务器健康状态与安全风险
  • 同步工具的底层依赖:AQS
  • Kubernetes 中为 ZenTao 的 Apache 服务器添加请求体大小限制
  • 如何开发一款高稳定、低延迟、功能全面的RTSP播放器?
  • 时序数据库选型指南:为何Apache IoTDB成为工业物联网首选
  • JVM分析(OOM、死锁、死循环)(JProfiler、arthas、jvm自带工具)
  • STM32 - Embedded IDE - GCC - 使用 GCC 链接脚本限制 Flash 区域
  • 【Android】从复用到重绘的控件定制化方式
  • HarmonyOS 应用开发深度解析:基于 ArkTS 的声明式 UI 与状态管理艺术
  • HarmonyOS安装以及遇到的问题
  • Jenkins-Ansible部署discuz论坛
  • 38.Ansible判断+实例
  • PINN物理信息神经网络用于求解二阶常微分方程(ODE)的边值问题,Matlab实现
  • 力扣hot100:缺失的第一个正数(哈希思想)(41)
  • Qwen3-30B-A3B 模型解析
  • 【C++】迭代器详解与失效机制
  • # Shell 文本处理三剑客:awk、sed 与常用小工具详解
  • 【前端面试题✨】Vue篇(一)
  • Linux网络序列化与反序列化(6)
  • Linux文本处理——awk
  • 飞牛OS Nas,SSH安装宝塔后,smb文件不能共享问题