android 内存泄露小计

1   今天在调试android 程序时候,发现即使程序退出了,发现还占用内存大概有15M.用MAT查看,经过多次GC操作,发现依旧是15.直觉告诉我,应该发生内存泄露了。然后利用MAT,查看Memory Leak。结果让我很吃惊,发现是InputMethodManager。这个对象一直引用着Context。也就是Activity,导致它无法释放内存。后来google 一下发现,

以下贴出解决办法,希望给遇到类似情况的人,提供帮助:

@Override
protected void onDestroy()
{
    super.onDestroy();
    //fix for memory leak: http://code.google.com/p/android/issues/detail?id=34731
    fixInputMethodManager();
}

private void fixInputMethodManager()
{
    final Object imm = getSystemService(Context.INPUT_METHOD_SERVICE);

    final Reflector.TypedObject windowToken
        = new Reflector.TypedObject(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);
}

就是通过反射调用windowDismissed和startGettingWindowFocus。本来以为这个问题就这样搞定了,谁知道又出现了一个更加奇葩的情况。我发现竟然还有一个更奇葩的对象:com.lflytek.speech.a.a.a。脑子懵了一下,这是啥东东?通过百度这个查询,发现这是科大讯飞的语音识别sdk。对,脑子确实懵了。但是不对啊。这个对象怎么生命周期那么长。不对,肯定哪里搞错了。后来通过源代码阅读:

public RecognizerDialog(Context paramContext, String paramString)
  {
    super(paramContext);
    this.a = new a(paramContext, paramString);
  }

  public void setListener(RecognizerDialogListener paramRecognizerDialogListener)
  {
    ((a)this.a).a(paramRecognizerDialogListener);
  }

这是sdk唯一能得到我应用程序的地方,其他的都是设置一些信息。难道问题就出在这个地方?对,你答对了!

表面上看起来这没有任何问题,你看我们很多应用程序sdk不都是这么弄的嘛,这很正常啊。没办法,虽然代码混淆过了,可我为了搞清楚事情真相只能硬着头皮去读。通过代码不断的追踪,终于发现秘密了。

在com.iflytek.speech.a.a中有一个很奇葩的私有的类成员。

private static a e=null

  public static com.iflytek.speech.b b(Context paramContext, String paramString)
  {
    if (e == null)
      e = new a(paramContext, paramString);
    return e;
  }

你这不是坑人吗?干嘛非要用静态呢,这样就造成了e的生命周期长与Activity,也就造成了内存泄露。(后来在看混淆过的科大讯飞sdk代码时,发现原来它在采集设备的位置信息和应用程序的包名和相关签名信息,当然这也无可厚非,人家毕竟要验证应用程序的包名和签名)。这可咋办,这个静态又是私有的。对了,想到反射了。

以下贴出反射的代码。

@Override
	public void finish() {
		com.iflytek.a.a.a=null;
		try {
			Class clazz=Class.forName("com.iflytek.speech.a.a");
			Field field=clazz.getDeclaredField("e");
			if (field.isAccessible()==false) {
				field.setAccessible(true);
			}
			field.set(null, null);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		super.finish();
	}

然后再调试,发现这个问题总算解决了。

看来以后用第三方sdk的时候,得注意点了,不能随便用啊。

时间: 2024-10-19 05:13:26

android 内存泄露小计的相关文章

android 内存泄露调试

一.概述 1 二.Android(Java)中常见的容易引起内存泄漏的不良代码 1 (一) 查询数据库没有关闭游标 2 (二) 构造Adapter时,没有使用缓存的 convertView 3 (三) Bitmap对象不在使用时调用recycle()释放内存 4 (四) 释放对象的引用 4 (五) 其他 5 三.内存监测工具 DDMS --> Heap 5 四.内存分析工具 MAT(Memory Analyzer Tool) 7 (一) 生成.hprof文件 7 (二) 使用MAT导入.hpro

Android内存泄露开篇

先来想这三个问题 内存泄露是怎么回事 内存会泄露的原因 避免内存泄露 1.内存泄露怎么回事 一个程序中,已经不需要使用某个对象,但是因为仍然有引用指向它垃圾回收器就无法回收它,当然该对象占用的内存就无法被使用,这就造成了内存泄露. Android的一个应用程序的内存泄露对别的应用程序影响不大. 为了能够使得Android应用程序安全且快速的运行,Android的每个应用程序都会使用一个专有的Dalvik虚拟机实例来运行,它是由Zygote服务进程孵化出来的,也就是说每个应用程序都是在属于自己的进

android内存泄露调试,Heap,MAT

三.内存监测工具 DDMS --> Heap 无论怎么小心,想完全避免bad code是不可能的,此时就需要一些工具来帮助我们检查代码中是否存在会造成内存泄漏的地方.Android tools中的DDMS就带有一个很不错的内存监测工具Heap(这里我使用eclipse的ADT插件,并以真机为例,在模拟器中的情况类似).用Heap监测应用进程使用内存情况的步骤如下: 1. 启动eclipse后,切换到DDMS透视图,并确认Devices视图.Heap视图都是打开的: 2. 将手机通过USB链接至电

Android内存泄露总结

Android可能发生内存泄露的地方总结: 1.查询数据库没有关闭游标 2.构建adapter时,没有使用缓存的convertView 3.Bitmap对象不使用的时候调用recycle()方法释放内存 4.释放对象的引用 5.单例模式引用context,如果使用actvitiy-context,会造成内存泄露, 可以使用getApplicationContext()); 或getApplication()代替. 参考文档: A?n?d?r?o?i?d? ?内?存?泄?漏?调?试 http://

Android内存泄露分析简要思路

工作中遇到挺多需要分析内存泄露问题的情况,现在大致简要写下思路,等之后时间相对比较充裕再进行补充. 1.明白内存泄露的判断依据? 个人总结为:持续增加,只增不减! 理解一下这8个字,配合几个命令和工具来确定一下你的应用是否存在内存泄露问题,这是很关键的,如果一开始就判断错误了,那么没有继续往下进行的理由. 命令如下: adb shell dumpsys meminfo 应用包名 [当然,比较粗略地话,可以用adb shell procrank] 这时候你可以看到一个内存使用情况表 而我们首先关注

Android 内存泄露

转:http://blog.chinaunix.net/uid-26930580-id-3844811.html 1.内存泄漏: 当出现对Activity.View或drawable等类的对象长期持有无用的引用,就会造成被引用的对象无法在GC时回收,而是长期占用堆空间,此时就会发生内存泄漏.简单来说,就是保留下来却永远不再使用的对象引用. 2.内存溢出: 如果应用程序在消耗光了所有的可用堆空间(16M到48M),那么再试图在堆上分配新对象时就会引起OOM(Out Of Memory Error)

android内存泄露相关研究【整体看】

在android项目开发的时候,内存问题一直都是很困扰我们的常见的问题,在实际开发中,如何在开发时就很好的约束&控制内存已经成为了一件恨重要的事情了. 1.为什么要在开发时就要约束内存 因为小编从事过不同类型的APP的开发,混合式语言开发是我们现在开发中使用最常见的一种,在不同的脚本语言的时候,我们的内存产生也会不一样. 列子:下面小编就拿1)非常原生的App2)hybrid web App3)lua脚本语言APP 备注:因为本人电脑问题,不能够添加图片,具体证明类图片会在后期闲置的时间添加 结

Android 内存泄露简介、典型情景及检测解决

什么是内存泄露? Android虚拟机的垃圾回收采用的是根搜索算法.GC会从根节点(GC Roots)开始对heap进行遍历.到最后,部分没有直接或者间接引用到GC Roots的就是需要回收的垃圾,会被GC回收掉.内存泄漏指的是进程中某些对象(垃圾对象)已经没有使用价值了,但是它们却可以直接或间接地引用到gc roots导致无法被GC回收.无用的对象占据着内存空间,导致不能及时回收这个对象所占用的内存.内存泄露积累超过Dalvik堆大小,就会发生OOM(OutOfMemory). 内存泄露的经典

JVM内存管理概述与android内存泄露分析

一.内存划分 将内存划分为六大部分,分别是PC寄存器.JAVA虚拟机栈.JAVA堆.方法区.运行时常量池以及本地方法栈. 1.PC寄存器(线程独有):全称是程序计数寄存器,它记载着每一个线程当前运行的JAVA方法的地址, 如果是当前执行的是本地方法,则程序计数器会是一个空地址.它的作用就是用来支持多线程,线程的阻塞.恢复. 挂起等一系列操作,直观的想象一下,要是没有记住每个线程当前运行的位置,又如何恢复呢.依据这一点, 每一个线程都有一个PC寄存器,也就是说PC寄存器是线程独有的. 2.JAVA