内存泄漏
来源:互联网 发布:量化交易编程语言 编辑:程序博客网 时间:2024/06/05 10:43
1 android monitor 点gc, 然后点dump java heap 获取hprof文件.
2 在sdk/platform-tools里面找到hprof-conv 打开cmd 输入命令hprof androidstudio.hprof mat.hprof (转化android stuido 格式的hprof成为 mathprof)
3 下载mat (eclipse memeory analizer) 打开进行分析
或者使用leak canary
开始使用
在 build.gradle
中加入引用,不同的编译使用不同的引用:
dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' //注意这里一定要用debugCompile否则leakcanary不会出现 releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5' }
在 Application
中:
public class ExampleApplication extends Application { @Override public void onCreate() { super.onCreate(); LeakCanary.install(this); }
第一步
打开ActivityB,leakcanary直接ANR
查StackOverFlow得知在6.0需要权限:WRITE_EXTERNAL_STORAGE
第二步
LeakCanary成功弹出通知
log打印:
- Reference Key: 42c5fe29-3abe-49bf-b745-2bae8b6e170a
- Device: Genymotion Android Google Nexus 5X - 6.0.0 - API 23 - 1080x1920 vbox86p
- Android Version: 6.0 API: 23 LeakCanary: 1.3.1
- Durations: watch=5020ms, gc=107ms, heap dump=2226ms, analysis=3173ms
但是通知详情里提示分析失败。。 leak analysis failed
升级LeakCanary到1.4 beta2后成功监测到内存泄露
第三步
可以看到内存泄露是TextView持有MainActivity引用造成的,最简单的解决办法就是取消sTextView的static关键字,那如果非要采用静态的呢?
我们再用Dump Heap查看一下
在MainActivity界面,Dump
可以看到ActivityB数量是0,MainActivity数量1
接下来我们启动ActivityB,然后点击initiate GC将MainActivity回收
可以看到MainActivity仍然没有被回收
那么该怎么解决呢?
想到用弱引用activity来findView,结果仍然泄露,因为find到的TextView对象还是持有Activity的引用
WeakReference<MainActivity> weakReference = new WeakReference<>(this);sTextView = (TextView) weakReference.get().findViewById(R.id.tv_text);
于是,弱引用textview,依然泄露。这里不懂为什么
sTextView = new WeakReference<>((TextView) findViewById(R.id.tv_text)).get();
怒了,在onDestory中释放资源
@Override protected void onDestroy() { super.onDestroy(); sTextView = null; }
成功!leakcanary不再监测到泄露。可以看到log里触发了GC
I/System.out: post delayed may leakI/art: Starting a blocking GC ExplicitI/art: Explicit concurrent mark sweep GC freed 539(43KB) AllocSpace objects, 0(0B) LOS objects, 40% free, 1483KB/2MB, paused 174us total 4.290ms
在ActivityB界面我们initial GC一下,发现MainActivity被回收了
这里Handler可能也会造成内存泄露,我们在打开ActivityB时,5秒内initial GC,然后LeakCanary就弹出了通知:
显然这里泄露了,我们改写Handler为静态内部类
// 解决Handler造成的内存泄露 private MyHandler mHandler = new MyHandler(this); public static class MyHandler extends Handler { private WeakReference<MainActivity> mWeakReference; public MyHandler(MainActivity activity) { mWeakReference = new WeakReference<>(activity); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); } }
再测试就不会发生这种问题了。
第四步
点击STARTALLOCATION按钮出现了内存抖动
log打印了一大堆100后停止打印,log最后三行如下,但是App没有ANR也没有FC。
s I/Choreographer: Skipped 60 frames! The application may be doing too much work on its main thread.W/EGL_emulation: eglSurfaceAttrib not implementedW/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0xdf81e4e0, error=EGL_SUCCESSE/Surface: getSlotFromBufferLocked: unknown buffer: 0xe02c5f70
打开Allocation Tracking 如图
发现MainActivity里有20001个对象,基本一半是Rect一半是StringBuilder。。。说明打印10000次是全部执行完了。这里可以发现,用+进行字符串拼接时,系统实际还是通过StringBuilder来拼接的
第五步
将MyView的onDraw方法中new对象的操作放到构造中,不然会造成内存抖动,因为onDraw会被频繁调用。
大概就这些。。没找到其他可优化的地方了
- 内存泄漏。。。
- 内存泄漏
- 内存泄漏
- 内存泄漏
- 内存泄漏
- 内存泄漏
- 内存泄漏
- 内存泄漏
- 内存泄漏
- 内存泄漏
- 内存泄漏
- 内存泄漏
- 内存泄漏
- 内存泄漏
- 内存泄漏
- 内存泄漏
- 内存泄漏
- 内存泄漏
- 使用CSS3滤镜开发模糊背景(毛玻璃)效果
- 用ReactJs编写的带斜线,行和列都分组的表格
- 搭建spring+dubbo环境步骤
- POJ 2387 Til the Cows Come Home 最短路
- MySQL记录
- 内存泄漏
- JavaScript Date对象用法及示例
- android 图片压缩工具类
- ASP.NET MVC4通过UrlRewriter配置伪静态
- 拉伸膜厂家揭秘为什么拉伸膜的层数越来越多
- Java中mysql拼接单引号和变量
- spring 的配置文件
- Tesseract-OCR
- SQl Server数据库学习总结