You need to enable JavaScript to run this app.
文档中心
应用性能监控全链路版

应用性能监控全链路版

复制全文
下载 pdf
最佳实践
使用内存泄漏监控和泄漏兜底服务
复制全文
下载 pdf
使用内存泄漏监控和泄漏兜底服务
本文以Android App应用为例,介绍App应用接入与使用内存泄漏的完整流程。
步骤一:获取SDK
  1. 在project级别的build.gradle文件中,添加maven地址。
  • buildscript {
    repositories {
    maven {
    url "https://artifact.bytedance.com/repository/Volcengine/"
    }
    maven {
    url "https://artifact.bytedance.com/repository/byteX/"
    }
    }
    }
    allprojects {
    repositories {
    maven {
    url "https://artifact.bytedance.com/repository/Volcengine/"
    }
    }
    }
  1. 接入应用性能监控全链路版。
  1. 在project级别的build.gradle文件的dependencies中,添加以下代码,接入插件组件辅助插桩。apm_insight_plugin 国内海外使用同一个版本。
  • classpath "com.volcengine:apm_insight_plugin:1.4.2"
  1. 在app module的build.gradle文件的dependencies中,添加以下代码,根据国内应用还是海外应用选择下面两个版本的一个。
  • 国内应用接入cn版本,上报到中国,使用如下依赖:
  • // 国内应用在dependencies中添加
    implementation 'com.volcengine:apm_insight:1.5.6.cn'
    implementation 'com.volcengine:apm_insight_crash:1.5.9'
  • 海外应用接入oversea版本,上报到马来西亚柔佛,使用如下依赖:
  • // 海外应用在dependencies中添加
    implementation 'com.volcengine:apm_insight:1.5.7.oversea'
    implementation 'com.volcengine:apm_insight_crash:1.5.8.oversea'
步骤二:初始化SDK并开启监控
  1. 在Application中onCreate中,添加以下代码,初始化性能相关功能。
注意
请在主线程中添加初始化性能相关功能的代码。
  • //必须放到Application的onCreate里面,会注册监听生命周期,不涉及数据采集和隐私合规问题
    ApmInsight.getInstance().init(application);
    //初始化自定日志,配置自定义日志最大占用磁盘,内部一般配置20,代表最大20M磁盘占用。1.4.1版本开始存在这个api
    VLog.init(this,20);
  1. 启动性能监控,开始收集数据。
注意
请在用户同意隐私政策后,再调用方法收集数据。
  • ApmInsightInitConfig.Builder builder = ApmInsightInitConfig.builder();
    //开启泄露和泄露兜底检测能力,泄露检测和泄露兜底需要分别在平台配置采样
    builder.detectActivityLeak(new IActivityLeakListener() {
    @Override
    public void onActivityLeaked(Activity activity) {
    //activity泄露的回调
    }
    });
    ApmInsight.getInstance().start(builder.build());
  1. 在app module的build.gradle文件最外层,添加以下代码,完成插桩。
  • 启动分析和页面体验相关功能依赖插件插桩,需配置ApmPlugin的whiteList为自己的包名,配置后该目录下的代码会被插桩。
  • ApmPlugin {// 是否进行插桩
    enable true// 是否在Debug包插桩,默认不插桩
    enableInDebug true// DEBUG("DEBUG"), INFO("INFO"), WARN("WARN"), ERROR("ERROR");// DEBUG 级别Log会汇总所有被插桩处理的类供查看,路径 app/build/ByteX/ApmPlugin/ApmPlugin_log.txt
    logLevel "DEBUG"// 启动分析开关:监控App启动耗时,需要同时开启pageLoadSwitch
    startSwitch = true// 页面响应开关:监控Activity的生命周期耗时
    pageLoadSwitch = true// 网络监控开关:监控okhttp3的网络请求
    okHttp3Switch = true//插桩显示HttpUrlConnection的网络请求开关
    httpUrlConnectionSwitch = true// 白名单下的包进行插桩,需要填写要插桩类所在的包名,支持前缀配置
    whiteList = ["com"
    ]// 黑名单包下类不进行插桩,可以配置包名和类名,没有可以填空
    blackList = ["com.xxx"
    ]
    }
步骤三:完成SDK上报配置
端上开启泄漏检测和泄漏兜底处理开关后,平台也可以控制泄漏检测和泄漏兜底处理,泄漏兜底处理依赖泄漏检测。详细操作步骤,请参见SDK上报配置
  1. 单击目标应用下的App端监控
  1. 在控制台左上角选择全部功能 > SDK上报配置
  1. 在筛选区域单击Android系统。
  1. 各模块采样率配置页签下,单击内存优化
  1. 在内存优化配置页面,打开总开关
  • 总开关打开会根据采样配置上报数据,关闭则整个模块不会上报数据。
  • Image
  1. 选择配置项为内存泄漏检测采样率,然后单击创建配置,修改采样率。
  1. 选择配置项为内存泄漏兜底采样率,然后单击创建配置,修改采样率。
  • Image
  • 内存泄漏检测采样率 :控制内存泄漏兜底方案是否开启泄露检测
  • 内存泄露兜底采样率:控制内存泄漏兜底方案是否进行泄露兜底
说明
请谨慎开启内存泄露兜底采样率,并逐渐增加采样率。兜底操作会把view的背景图置空,防止有不当逻辑在Activity onDestroy后依然有操作view背景图产生异常。
步骤四:配置泄漏事件
端上检测到泄露事件后,如果判断平台配置了泄露事件上报,会把泄露的Activity名称上报到平台,这样平台就可以查看哪个页面泄露的次数较多。但因为泄露引用链需要dump内存才能解析出来,性能影响较大,这里并不不会dump内存快照解析泄露引用链,只是作为泄露的监控指标。具体泄露引用链可以通过接入OOM崩溃时候dump内存解析出泄露排查问题。
  1. 在控制台左上角选择全部功能 > 事件管理
  1. 在筛选区域单击Android系统,然后单击新增事件
  1. 在新建事件页面,完成以下配置,然后单击创建
  • Image
  • 配置项说明:
  • 配置区域
    配置项
    说明
    示例
    事件信息
    事件名称
    自定义名称,用于标识该事件。不能与已有事件名重复。
    apmplus_activity_leak_monitor
    事件描述
    输入事件描述。
    系统
    选择系统,支持选择Android和iOS。
    Android
    标签
    选择标签。便于查找该事件。
    指标/维度信息
    名称
    输入指标或者维度的名称。
    leak_activity
    类型
    选择类型,支持选择指标和维度。
    • 维度:如果您只想查看自定义数据的上报量,选择自定义维度
    • 指标:您想查看自定义数据的上报量、平均值和PCT值,选择自定义指标
    维度
    描述
    输入对指标或者维度的描述。
    上报配置
    规则名称
    自定义规则名称,用于标识该规则。
    全量采集
    采样率
    配置采样率。
    事件上报量与收费相关,采样率应根据业务量大小合理配置。
    100%
    规则条件
    配置规则,当满足该规则时上报事件。
步骤五:查看泄漏事件
  1. 在控制台左上角选择全部功能 > 事件趋势
  1. 在筛选区域单击Android系统,以及其他业务相关的筛选项。
  1. 在左侧上报量页签中,单击泄漏事件名称apmplus_activity_leak_monitor,选择维度leak_activity,然后在维度列表中单击维度名称leak_activity。
  1. 在详情页面查看leak_activity指标泄漏详情。
  • Image
原理说明
如果Android客户端实现的需求有不当的代码实现,就会导致Activity泄漏。Activity的泄漏会牵连一系列的对象,特别是各种View和他们的背景图Bitmap会占据大量的内存,是内存泄漏非常重要的占比。泄漏分析支持检测上报Activity泄露情况,还可以兜底Activity泄露导致的内存泄露,即断掉View对图片的引用,减少泄露内存。
基本概念
概念
说明
什么是内存泄漏?
在计算机中,由于疏忽或错误造成程序未能释放已经不再使用的内存,叫做内存泄漏。
在Java中,存在一些被分配的对象。
  • 这些对象是可达的,即在有向图中,GC ROOT存在通路可以与其相连**。**
  • 这些对象是无用的,即程序以后不会再使用这些对象。
如果对象满足这两个条件,这些对象就可以判定为Java中的内存泄漏,这些对象不会被GC所回收,然而它却占用内存。
如何检测Activity是泄露的?
一个Activity如果已经执行了onDestroy(),那么他的生命周期已经结束,不应该被任何对象所引用。在下一次GC回收的时候应该把执行了onDestroy()的Activity回收掉。如果执行了GC依然没有被回收,则判定当前Activity有强引用,已经泄露。
如何判断执行了GC?
支持代码主动触发GC,但是频繁GC对APP的整理运行并不友好,可能会造成卡顿。所以支持配置延迟检测Activity泄露,尽可能的让系统自己触发GC回收,而不是人为主动触发。
在Activity onDestroy后时建立一个WeakReference对一个new Object()的引用,如果这个new Object()被回收则认为触发了GC。
如何判断Activity是否被回收?
使用 WeakReference(T referent, ReferenceQueue<? super T> q)包装Activity,在Activity被垃圾回收器回收后,reference会被放入内部的ReferenceQueue中。
也就是说,从队列ReferenceQueue取出来的所有reference,它们指向的真实对象都已经成功被回收了。
什么是内存泄漏兜底?
一些泄漏的对象的生命周期已经结束,但依然存在着强引用,导致对象没有办法被GC回收。通过代码主动断开泄露对象到GC ROOT的链路,或者释放掉泄露对象的引用对象,让这些泄露对象在下次GC时候可以被回收掉,释放出内存空间,这就是内存泄露兜底。它就像一个自动扫地机器人,不断地帮您在房间清理垃圾。
内存泄漏兜底处理哪些对象?
  • 谁占用的内存较大
  • 谁泄露的频率较高
  • 确认兜底后尽量不会有业务逻辑再去访问泄露对象,防止产生空指针异常。
通过延时处理泄露Activity持有View树的背景图和ImageView的图片,在Activity泄露后把背景图和ImageView的图片置空,防止图片泄露。
当然更激进的可以把RootView的所有子View全都Remove掉,但是业务使用复杂,很有可能在Remove后,依然有对View树的处理,产生空指针异常。
最近更新时间:2026.02.10 19:56:26
这个页面对您有帮助吗?
有用
有用
无用
无用