Leakcanary部分泄露警报无需修复

2024-06-10 12:08

本文主要是介绍Leakcanary部分泄露警报无需修复,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

转载自:

https://lynn8570.github.io/posts/some%20memory%20leaks%20that%20no%20need%20to%20be%20fixed/

前言

使用leakcanary检查内存泄露之后,由于他的工作原理,造成所有的在上下文关闭之后,还未被释放的资源就会引爆内存泄露通知。但是不是所有的泄露都需要修复的。下面总结几个我的血泪史,希望以后不要重蹈覆辙。

#InputMethodManager.sInstance泄露

输入法泄露,具体的泄露路径类似于

提示InputMethodManager.sInstance这个静态实例可能通过各种路径对context进行了泄露。具体的路径可能会不一样,但是归根到最后都是提示InputMethodManager.sInstance静态引用泄露。 通过网上搜索,可能有类似的修复,如下 public static final class TypedObject { private final Object object; private final Class type;

    public TypedObject(final Object object, final Class type){this.object = object;this.type = type;}Object getObject(){return object;}Class getType(){ return type;}
}public static void invokeMethodExceptionSafe(final Object methodOwner, final String method, final TypedObject... arguments)
{if (null == methodOwner){return;}try{final Class<?>[] types = null == arguments ? new Class[0] : new Class[arguments.length];final Object[] objects = null == arguments ? new Object[0] : new Object[arguments.length];if (null != arguments){for (int i = 0, limit = types.length; i < limit; i++){types[i] = arguments[i].getType();objects[i] = arguments[i].getObject();}}final Method declaredMethod = methodOwner.getClass().getDeclaredMethod(method, types);declaredMethod.setAccessible(true);declaredMethod.invoke(methodOwner, objects);}catch (final Throwable ignored){}
}public static void fixInputMethodManager(Activity activity)
{final Object imm = activity.getSystemService(Context.INPUT_METHOD_SERVICE);final Reflector.TypedObject windowToken= new Reflector.TypedObject(activity.getWindow().getDecorView().getWindowToken(), IBinder.class);Reflector.invokeMethodExceptionSafe(imm, "windowDismissed", windowToken);final Reflector.TypedObject view= new Reflector.TypedObject(null, View.class);Reflector.invokeMethodExceptionSafe(imm, "startGettingWindowFocus", view);
}

主要通过反射,修复内存泄露。

但是,下面的话,非常重要,非常重要,非常重要,重要的事情说三遍:这个属于系统级别的泄露,也就是说,你不泄露,别人也会泄露,而且整个android系统,只保留一个static instance的引用,所以这个修复,对整个系统的内存没有太大的改善。而且这个修复的隐患是,你有可能会在页面跳转的时候,遇到各种不可预测的编辑框无法获取焦点的问题。所以,我建议,这个泄露,可以忽略。

AsyncQueryHandler 没有quit

有时候我们会遇到HandlerThread没有quit而爆出的泄露,泄露路径如下:

而android系统中有个AsyncQueryWorker从源代码看

public AsyncQueryHandler(ContentResolver cr) {super();mResolver = new WeakReference<ContentResolver>(cr);synchronized (AsyncQueryHandler.class) {if (sLooper == null) {HandlerThread thread = new HandlerThread    ("AsyncQueryWorker");thread.start();sLooper = thread.getLooper();}}mWorkerThreadHandler = createHandler(sLooper);
}

这个名为AsyncQueryWorker的HandlerThread自从start之后就没人管了。这个时候,leakcanary也会提示泄露。 于是我曾自作聪明,通过反射将这个sLooper强制退出,代码如下:

//linlian@2015.06.01 release static sLooper in AsyncQueryHandler
public static void fixAsyncQueryWorker(){Field sLooperCached = null;try {sLooperCached = Class.forName("android.content.AsyncQueryHandler").getDeclaredField("sLooper");sLooperCached.setAccessible(true);} catch (Exception ex) {ex.printStackTrace();}if (sLooperCached == null) return;Looper looper = null;try {// Get reference to the sLooperCached looper = (Looper)sLooperCached.get(null);if(looper!=null){looper.quit();sLooperCached.set(null,null);}} catch (Exception ex) {ex.printStackTrace();}

这个修复的惨痛后果是,有些后台线程直接结束了,所以,对于AsyncQueryHandler的泄露,我也是建议不修复。

TextLine.sCached 泄露

和inputManager一样,这个泄露,属于系统的静态引用而造成的泄露,但是这个泄露的修复,目前没有发现什么不良的影响,但是泄露修复的价值意义不知道大不大,也是你不泄露,别人也会泄露,反正总有一个这样的引用存在的。修复的效果也不是很明显 修复代码如下

public static void clearTextLineCache(){Field textLineCached = null;try {textLineCached = Class.forName("android.text.TextLine").getDeclaredField("sCached");textLineCached.setAccessible(true);} catch (Exception ex) {ex.printStackTrace();}if (textLineCached == null) return;Object cached = null;try {// Get reference to the TextLine sCached array.cached = textLineCached.get(null);} catch (Exception ex) {ex.printStackTrace();}if (cached != null) {// Clear the array.for (int i = 0, size = Array.getLength(cached); i < size; i ++) {Array.set(cached, i, null);}}
}

总结

LeakCanary是一个很好检查内存泄露的工具,但不是所有的泄露都需要修复,有些事android系统的泄露bug,通过各种方式曲线救国之后,不一定会达到一个很好的内存改善结果,所以干脆不要去动他,以免引起不可预测的运行异常。只有自己非常肯定的,由于使用不规范等引起的内存泄露才是我们重点关注的部分

这篇关于Leakcanary部分泄露警报无需修复的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1048122

相关文章

poj 2976 分数规划二分贪心(部分对总体的贡献度) poj 3111

poj 2976: 题意: 在n场考试中,每场考试共有b题,答对的题目有a题。 允许去掉k场考试,求能达到的最高正确率是多少。 解析: 假设已知准确率为x,则每场考试对于准确率的贡献值为: a - b * x,将贡献值大的排序排在前面舍弃掉后k个。 然后二分x就行了。 代码: #include <iostream>#include <cstdio>#incl

基于51单片机的自动转向修复系统的设计与实现

文章目录 前言资料获取设计介绍功能介绍设计清单具体实现截图参考文献设计获取 前言 💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们电子相关专业的大学生,希望您们都共创辉煌!✌💗 👇🏻 精彩专栏 推荐订阅👇🏻 单片机

笔记整理—内核!启动!—kernel部分(2)从汇编阶段到start_kernel

kernel起始与ENTRY(stext),和uboot一样,都是从汇编阶段开始的,因为对于kernel而言,还没进行栈的维护,所以无法使用c语言。_HEAD定义了后面代码属于段名为.head .text的段。         内核起始部分代码被解压代码调用,前面关于uboot的文章中有提到过(eg:zImage)。uboot启动是无条件的,只要代码的位置对,上电就工作,kern

【经验交流】修复系统事件查看器启动不能时出现的4201错误

方法1,取得『%SystemRoot%\LogFiles』文件夹和『%SystemRoot%\System32\wbem』文件夹的权限(包括这两个文件夹的所有子文件夹的权限),简单点说,就是使你当前的帐户拥有这两个文件夹以及它们的子文件夹的绝对控制权限。这是最简单的方法,不少老外说,这样一弄,倒是解决了问题。不过对我的系统,没用; 方法2,以不带网络的安全模式启动,运行命令行,输入“ne

项目实战系列三: 家居购项目 第四部分

购物车 🌳购物车🍆显示购物车🍆更改商品数量🍆清空购物车&&删除商品 🌳生成订单 🌳购物车 需求分析 1.会员登陆后, 可以添加家居到购物车 2.完成购物车的设计和实现 3.每添加一个家居,购物车的数量+1, 并显示 程序框架图 1.新建src/com/zzw/furns/entity/CartItem.java, CartItem-家居项模型 /***

码蹄集部分题目(2024OJ赛9.4-9.8;线段树+树状数组)

1🐋🐋配对最小值(王者;树状数组) 时间限制:1秒 占用内存:64M 🐟题目思路 MT3065 配对最小值_哔哩哔哩_bilibili 🐟代码 #include<bits/stdc++.h> using namespace std;const int N=1e5+7;int a[N],b[N],c[N],n,q;struct QUERY{int l,r,id;}que

全英文地图/天地图和谷歌瓦片地图杂交/设备分布和轨迹回放/无需翻墙离线使用

一、前言说明 随着风云局势的剧烈变化,对我们搞软件开发的人员来说,影响也是越发明显,比如之前对美对欧的软件居多,现在慢慢的变成了对大鹅和中东以及非洲的居多,这两年明显问有没有俄语或者阿拉伯语的输入法的增多,这要是放在2019年以前,一年也遇不到一个人问这种需求场景的。 地图应用这块也是,之前的应用主要在国内,现在慢慢的多了一些外国的应用场景,这就遇到一个大问题,我们平时主要开发用的都是国内的地

控制台和MFC中内存泄露工具vld的使用

最近想检测下项目中内存泄露的情况,选中了vld这款。在查找使用方法的时候,大都是控制台下的示例,添加到main函数所在的源文件上。换成MFC就纠结了,不知道添加到哪里去。本文记录控制台和MFC中的使用vld过程。    vld资源:    1)、大家可以移步下边的网址下载:     http://vld.codeplex.com/releases/view/82311    2

关于断言的部分用法

1、带变量的断言  systemVerilog assertion 中variable delay的使用,##[variable],带变量的延时(可变延时)_assertion中的延时-CSDN博客 2、until 的使用 systemVerilog assertion 中until的使用_verilog until-CSDN博客 3、throughout的使用   常用于断言和假设中的

用VB创建开始菜单快捷方式(无需其他DLL)

Option Explicit   Private Sub Command1_Click()   CreateProgManGroup Me, "测试", "test.grp"   CreateProgManItem Me, "d:\ghost.exe", "Ghost"   CreateProgManItem Me, "d:\setupQQ.exe", "QQ"   End