简单粗暴!Android Activity泄漏问题解决方案
2016-07-29 12:13
309 查看
http://wetest.qq.com/lab/view/63.html
测试跟你说你的XXActivity泄露了,你如何确认是否真的泄漏?
确认泄漏后,你又如何定位是哪里的问题导致内存泄漏?
Android日常开发中,内存泄漏的重灾区就是Activity,相信这两个是每个Android开发者都碰到过的问题,遇到这种问题,我们一般都会祭出我们的杀手锏:Dump Java Heap然后MAT静态分析GC链。然后今天我想另辟蹊径,从更简单的角度定位并解决这种问题。
如果我们想确认这个Activity是否存在泄漏,只需让其覆盖Object的finalize方法,在里面添加一句Logcat打印:
然后运行你的项目,打开这个Activity,然后按返回,退出Activity,然后通过IDE强制触发一次GC操作:
(Android Studio)
(Eclipse)
然后查看Logcat,是否有对应的打印,就能确认Activity是否存在内存泄漏了:有打印,则无内存泄漏,无打印则肯定有内存泄漏了!
然后再进出一次Activity,触发GC,确认Activity泄漏已经不存在。然后再把业务逻辑一个个补回来,直到泄漏现象重现。
这样我们就能100%的找出泄漏的原因所在。
测试跟你说你的XXActivity泄露了,你如何确认是否真的泄漏?
确认泄漏后,你又如何定位是哪里的问题导致内存泄漏?
Android日常开发中,内存泄漏的重灾区就是Activity,相信这两个是每个Android开发者都碰到过的问题,遇到这种问题,我们一般都会祭出我们的杀手锏:Dump Java Heap然后MAT静态分析GC链。然后今天我想另辟蹊径,从更简单的角度定位并解决这种问题。
确认泄漏
我们先来看一个抽象的Activity伪代码:public class LeakActivity extends Activity { ComplexLogicA; // 复杂的业务逻辑代码 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ComplexLogicB; // 复杂的业务逻辑代码 LeakLogic; // 引起泄漏的业务逻辑代码 ComplexLogicC; ComplexLogicD; } @Override protected void onResume() { super.onResume(); ComplexLogicE; ComplexLogicF; ComplexLogicG; } OtherComplexLogin... // 其他业务逻辑代码 }
如果我们想确认这个Activity是否存在泄漏,只需让其覆盖Object的finalize方法,在里面添加一句Logcat打印:
public class LeakActivity extends Activity { ComplexLogicA; // 复杂的业务逻辑代码 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ComplexLogicB; // 复杂的业务逻辑代码 LeakLogic; // 引起泄漏的业务逻辑代码 ComplexLogicC; ComplexLogicD; } @Override protected void onResume() { super.onResume(); ComplexLogicE; ComplexLogicF; ComplexLogicG; } @Override protected void finalize() throws Throwable { super.finalize(); Log.d("", "====LeakActivity has been recycled!"); } OtherComplexLogin... // 其他业务逻辑代码 }
然后运行你的项目,打开这个Activity,然后按返回,退出Activity,然后通过IDE强制触发一次GC操作:
(Android Studio)
(Eclipse)
然后查看Logcat,是否有对应的打印,就能确认Activity是否存在内存泄漏了:有打印,则无内存泄漏,无打印则肯定有内存泄漏了!
定位泄漏原因
定位泄漏原因这个就是比较简单粗暴的排除法,首先把所有复杂业务逻辑注视掉,直到内存泄漏现在不存在:public class LeakActivity extends Activity { // ComplexLogicA; // 复杂的业务逻辑代码 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ComplexLogicB; // 复杂的业务逻辑代码 // LeakLogic; // 引起泄漏的业务逻辑代码 // ComplexLogicC; // ComplexLogicD; } @Override protected void onResume() { super.onResume(); // ComplexLogicE; // ComplexLogicF; // ComplexLogicG; } @Override protected void finalize() throws Throwable { super.finalize(); Log.d("", "====LeakActivity has been recycled!"); } // OtherComplexLogin... // 其他业务逻辑代码 }
然后再进出一次Activity,触发GC,确认Activity泄漏已经不存在。然后再把业务逻辑一个个补回来,直到泄漏现象重现。
这样我们就能100%的找出泄漏的原因所在。
知识点
这里用到的一个知识点就是Java中Object类的finalize方法。当GC准备回收一个Java Object(所有Java对象都是Object的子类)的时候,GC会调用这个Object的finalize方法。这个方法有点类似于C++中析构函数,本意是让你用来回收一些已经不需要的资源的(主要是针对Native资源)。其实Java日常开发中,并不鼓励依赖于这个方法来实现回收的逻辑,因为如果你重度依赖于finalize的话,finalize本身也有可能造成内存泄漏,但是我们这里只是用来作为是否已经回收的依据,还是可以的。总结
虽然此方法看起来比较简单无脑,但是简单粗暴啊,也不失为给开发的一种便利的自测方式,不用其他工具就可以快速的确定你这次的需求新增的Activity是否存在泄漏,权当减少自己Bug数的一种方法吧!相关文章推荐
- 突出一个简单粗暴!Android Activity泄漏问题解决方案
- Android Activity泄漏问题解决方案
- 突出一个简单粗暴!Android Activity泄漏问题解决方案
- 突出一个简单粗暴!Android Activity泄漏问题解决方案
- 突出一个简单粗暴!Android Activity泄漏问题解决方案
- Android中遇到问题时的解决方案:突出一个简单粗暴!Android Activity泄漏问题解决方案
- 突出一个简单粗暴!Android Activity泄漏问题解决方案
- android activity界面调整黑屏问题解决方案
- 解决Android使用ActivityGroup打开Activity后控件无法居中问题
- android真机调试 INSTALL_FAILED_MEDIA_UNAVAILABLE 问题解决方案
- Android 完美解决自定义preference与ActivityGroup UI更新的问题
- Android中不同Activity之间传递自定义对象的参数问题的解决
- [Android] Activity not started 问题解决
- android中ListView异步加载图片时的图片错位问题解决方案
- 解决 Android中用里ScrollView 之后 Activity 中的 onTouchEvent 失效问题
- 解决Android中Fragment调用startactivityforresult不能返回结果的问题
- Android 完美解决自定义preference与ActivityGroup UI更新的问题
- Android问题集锦之八:调用其他程序中的activity和Permission Denial: starting Intent 错误解决办法
- Android应用点击HOME后,再次启动该应用,不显示最近Activity的问题解决。
- Android 输入法键盘和activity页面遮挡问题解决