赞
踩
在App开发过程中,可能会有小伙伴在Logcat中看到过这个信息:
Background concurrent copying GC freed 282965(11MB) AllocSpace objects,
39(7MB) LOS objects, 42% free, 23MB/41MB, paused 248us total 207.041ms
这条信息表明,Java的垃圾回收机制,帮我们进行了垃圾回收。释放了11M内存,28万多个对象。一段时间内,app内部创建了大量对象。接下来我们借助Profiler,定位到这个问题。
首先进行场景还原。
创建一个Activity,Activity中只有一个Button,点击Button会创建大量的对象。
/** * button点击事件 * @param view */ public void allocate(View view) { int sum = 20*1000; for (int i = 0; i < sum; i++) { new ByteArr(); } } class ByteArr{ private byte[] b; public ByteArr() { b = new byte[40]; for (int i = 0; i < b.length; i++) { b[i] = (byte) (i/126); } } }
点击一次Button,创建20万个ByteArr对象,每个ByteArr对象至少40个字节。
然后我们运行App,打开profiler,选择我们运行的进程。
接着点击Memory。
这里有两个选项:第一个,记录特定时间点,内存的试用情况;第二个,查看一段时间内,Java或者kotlin对象的创建情况。这里我们用到的是第二个选项,无法看到第二选项的小伙伴,尝试升级下android studio;
当我们点击Record后,就可以开始不断点击Button,大量创建对象了。我们盯着顶部的memory,当出现垃圾桶图标,表示已经进行了垃圾回收,点击上方的红色圆点,停止记录。
为了方便查看,选择按照package分类
关注Allocations那一列,可以看到,在我们点击Button的这段时间内,创建了21188个ByteArr。
点击Table旁边的Visualization,Profiler会用图形的方式展现,这个过程会造成界面IDE界面卡顿,需要耐心等待一下。
选择Allcation Count。
这里不仅展示了对象的创建数量,还贴心的描述了创建路径。
比如上图的第一列,可以很方便的定位到源代码位置。
将指针悬浮在一个方法上,profiler会告诉我们这个方法执行过程中,创建了多少个对象。
切换到Allocation Size,查看创建对象的分配内存。
指针悬浮在方法上时,显示方法执行后,消耗了多少内存。
工欲善其事必先利其器,掌握了内存分析,写出高质量的App,指日可待。
频繁gc,可能是写代码时的疏忽导致了。但是无法避免频繁创建对象怎么办?推荐去阅读Handler源码,重点查看Message类的obtain()和recycle()。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。