匿名Thread治理 -- 字节码增强

背景

  1. 在某种场景下会无限制的创建新线程,最终导致 OOM
  2. 在某一时间应用内的线程数达到数百甚至上千
  3. 即使在空闲的时候,线程池中的线程一直在 WAITING

这些现象最终导致的问题是:Out Of Memory

治理以上问题的难点之一在于

  1. 研发通常匿名创建了线程
  2. 无法修改第三方包中匿名线程

Android 创建匿名线程主要是通过以下几种方式:

  • Thread 及其子类
  • Timer 及其子类

目标

给匿名线程添加className + methodName

方案

通过ASM技术,在编译期间拦截transform,对匿名线程添加className + methodName

编译前源码:

image
image
image

编译后自动补全className + methodName:

image

分析Thread相关问题时,可根据Name定位到对应线程:

image

项目ASM框架参考booster,实现逻辑涉及到业务,不方便提供,不过了解了这种思路很容易也能实现

使用方法

在项目根目录中build.gradle中添加以下红色代码:

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    repositories {
        google()
        mavenCentral()
        maven { url 'http://artifactory.d.xiaomi.net/artifactory/artifactory-releases' }
    }
    dependencies {
        classpath "com.android.tools.build:gradle:4.2.2"

        classpath "com.didiglobal.booster:booster-gradle-plugin:4.0.0"
        classpath 'com.mi.bytem:bytem:1.0.2-SNAPSHOT'
    }
}

...

接下来在 Android 工程的 build.gradle添加以下红色代码:

plugins {
    id 'com.android.application'
    id 'com.didiglobal.booster'
}

android {
    ...
}
...

验证插件是否生效

  • 编译Log是否有以下输出
image
  • 查看app/build/intermediates/transforms/booster是否存在,并可在此目录下查看最终编译后的transforms之后的文件是否符合预期
image

Tips

使用以上方式可以帮助使用者分析定位业务代码、第三方库中匿名线程问题,但本质原因还是使用者创建了匿名线程,因此最好的解决办法还是在code-review时拒绝匿名线程的代码。

你可能感兴趣的:(匿名Thread治理 -- 字节码增强)