在Android 项目时的防止Memory leak 要注意的事项

翻译 2012年03月21日 16:20:13

一般来说,Java VM是会有Gargage Collect的。但是如果object在其他的object 有reference的话,那VM是不会做cleanup的。

常见的例子是在Activity 上发生。

因为在a) 由一个activity 跳到另一个activity 或是b)在screen rotation 时,Android 系统会新建一个新的Activity,而原先的Activity 会被释放,最后会被Gargage Collect.。但如果其他的Class 有用上这个Activity ,这个activity 就不会被Gargage Collect,因而引起memory leak 的问题。

例子

public class MyActivity extends Activity {

	public void onCreate(Bundle icicle) {
		super.onCreate(icicle);
		Utility.registerCallback(this);
	}
}

public class Utility {

	private static Classback m_callback = new Callback();

	public static void registerCallback(Context c) {
		m_callback.registerCallback(c);
	}
}

public class Callback {

	private context m_context;

	public void registerCallback(Context c) {
		m_context = c;
	}

	public void unregisterCallback(Context c) {
		if (c == m_context) {
			m_context = null;
		}
	}

}

在以上的例子中,因为class Callback 中的m_context 把 MyActivity 抓着了。 所以在这个Activity完成后,Garage Collect是不可以释放MyActivity 的。

一个解决方案是在Activity离开前,释放在外面的reference。  

例子

public class MyActivity extends Activity {

	public void onCreate(Bundle icicle) {
		super.onCreate(icicle);
		Utility.registerCallback(this);
	}

	public void onDestroy() {
		super.onDestroy();
		Utility.unregisterCallback(this);
	}
}

public class Utility {

	private static Classback m_callback = new Callback();

	public static void registerCallback(Context c) {
		m_callback.registerCallback(c);
	}

	public static void unregisterCallback(Context c) {
		m_callback.unregisterCallback(c);
	}
}

public class Callback {

	private context m_context;

	public void registerCallback(Context c) {
		m_context = c;
	}

	public void unregisterCallback(Context c) {
		if (c == m_context) {
			m_context = null;
		}
	}

}

其他的相关事项

1)在SDK中的DigitalClock Widget ,因为DigitalClock要注册一个observer,所以会用把载上DigitalClock widget的Activity作为那个observer。但在SDK的DigitalClock是有一个Bug的,因为在DigitalClock 的onDetachedFromWindow中是没有unregister 那个observer的。 解决方法是自己写一个DigitalClock。详情请看附上的代码(DigitalClockNew.java)。

2)在SDK中的Toast的function makeText 是要求传一个Context的,但在Toast的代码中,这个Context是会用做callback上。如果是传Activity作为那个 Context的话,那会发生memory leak的问题。解决方法是传 Application Context,而不是ActivityContext。

如何查看Memory leak的问题

如果怀疑有memory leak的问题,可先执行那个apk在emulator上,然后在PC上执行adb shell,,然后执行ps,查看你的process 的pid。

在apk上执行有memory leak可疑的动作后,可以做下面的诊断

1.  执行 dumpsys meminfo <pid>

这个指令显示pid的memory资料。注意是 Activity的 数量,如果数量是不断上升,那就是有memory leak。 注意,因为在未执行Gargage Collect前,Activity是不会被释放的。可以在DDMS上执行手动的Gargage Collect。

2. 把process 的memory dump 出来,看memory leak的所在

先执行 chmod 777 /data/misc,然后执行 kill -10 <pid> ,在 /data/misc 上会看到那个pid 的memory leak,(如heap-dump-tm1265266619-pid1673.hprof )

adb pull ( 如adb pull /data/misc/ heap-dump-tm1265266619-pid1673.hprof 1673.hprof )把这个档案拷回电脑上。

然后,用在PC上执行hprof-conv (如hprof-conv  1673.hprof  1673_a.hprof) 把那个拷回来的hprof转换成 Eclipse Memory Tool 可以支持的格式。

用Eclipse Memory Tool (http://www.eclipse.org/mat/), 打开转换了的memory dump。 在Eclipse Memory Tool 上,按OQL,输入 “select * from instanceof android.app.Activity” , 这个指令可以找所以在系统上是android.app.Activity 的 instance。(详见下图)

如果在object的旁带有“Unknown”的话,那object是可以被Gargage Collect的。要看其他的object是什么原因不可以被Gargage Collect 的话,可以在那个object上right-click,然后选Path to GC Roots, exclude weak/soft reference 。 (weak 和soft reference 都是可以被VM查到的,所以是可以Gargage Collect的。)

在Path to GC Roots 中,可以看到WidgetManagerHome 是因为Toast中的inner class TN 把 这个WidgetManagerHome抓住了。


在Android 项目时的防止Memory leak 要注意的事项

一般来说,Java VM是会有Gargage Collect的。但是如果object在其他的object 有reference的话,那VM是不会做cleanup的。 常见的例子是在Activity 上...
  • fangxiao37
  • fangxiao37
  • 2013年09月11日 19:30
  • 518

解决tomcat报错memory leak问题

异常如下:  2012-2-9 17:43:12 org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc 严重: The ...
  • u013493370
  • u013493370
  • 2016年03月21日 14:27
  • 3122

使用memcache 心得和注意事项

内存分配机制:首先要说明的是Memcached支持最大的存储对象为1M。它的内存分配比较特殊,但是这样的分配方式其实也是对于性能考虑的,简单的分配机制可以更容易回收再分配,节省对于CPU的使用。这里用...
  • stuartjing
  • stuartjing
  • 2012年12月06日 17:06
  • 4116

tomcat多次部署项目导致memory leak

这几日,忙着把改好的项目远程部署到web服务器上(tomcat原谅我还在用tomcat)之前也远程部署过一次,用的无线网,网速过慢第一次还没有成功。没办法吃完饭继续,累了趴了一会儿,没想到醒来就传好了...
  • zzj806683450
  • zzj806683450
  • 2014年11月05日 11:33
  • 5603

自定义函数,函数的使用注意事项,自定义对象,对象直接量

4  自定义函数 : 如果一段代码需要被重复编写和使用,那么我们未来方便统一编写使用,可以将其封装近一个函数(方法)中。 作用:增强代码的复用性 函数格式: function 方法名(参数列表){ ...
  • boss_way
  • boss_way
  • 2017年10月28日 15:01
  • 247

性能优化之内存泄露(Memory Leak)常用分析工具(另3种)

1 Lint分析工具(效果非常好)(1)概述 lint是随Android SDK自带的一个静态代码分析工具。它用来对Android工程的源文件进行检查,找出在正确性、安全、性能、可使用性、可访问性及...
  • chenliguan
  • chenliguan
  • 2016年11月14日 21:45
  • 958

[转] 解决 iphone的 memory leak 问题

加深一下,对内存分配的理解,解决 memory leak的问题 http://www.streamingcolour.com/blog/tutorials/tracking-iphone-memory...
  • situz
  • situz
  • 2009年07月23日 18:54
  • 866

使用memcache的一些注意点(一)

connect()总是会初始化链接池。不管前面是否调用了 addServer(),或者有其他的链接 例如: $mmc = new Memcache()  $mmc->addServer('node...
  • u013169722
  • u013169722
  • 2013年12月25日 00:52
  • 806

Android memory leak detect

What is memory leak Native process memory leak detect Java process memory leak detect Kmemleak usage...
  • kongxinsun
  • kongxinsun
  • 2017年11月29日 15:10
  • 114

编程中的一些注意事项

               1、refactoring的基本方法就是每一步小小变化,每一步测试。        2、如果发现需要为一个程序添加一个特性,而代码结构使你无法很方便的那么做,那就先重构那...
  • casularm
  • casularm
  • 2004年10月27日 21:06
  • 2826
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:在Android 项目时的防止Memory leak 要注意的事项
举报原因:
原因补充:

(最多只允许输入30个字)