1. 内存抖动的原因及引发的问题
在android虚拟机中,创建了大量的对象而这些对象的生命周期很短,虚拟机会将其标记为垃圾进行回收从而导致虚拟机在标记垃圾的过程中会出现stop the Wrold。什么是stop the world呢?在java字节码中我们知道创建一个对象需要如下三个字节码指令new
、dup
、invokespecial
,也就是说一个对象被创建的过程有三个原子操作。虚拟机中判断一个对象是否是垃圾有两种方式,一个是通过引用计数
,该种方式有相互引用的问题,通过引用计数导致垃圾不能彻底标记如何解决呢?
。另一种方式是通过根可达
的方式.如果在标记是否是垃圾的线程和创建对象的线程同时工作(创建对象的现场刚执行完new指令,标记垃圾的线程就扫描到了刚刚创建出来的对象)
,那么该对象还没有和变量obj
进行关联就被标记为垃圾,后面gc时将该对象进行了回收,在使用变量obj
时就会导致NullPointerExcetion,因此标记垃圾的线程和工作线程不能同时运行,因此在标记是否是垃圾的时候其他所有工作线程都需要停止。那么如果标记垃圾的时间太长,而工作线程又不能工作,应用就会出现卡顿的情况,因此我们要避免创建大量生命周期很短的对象。
1.1总结
1.1.1 内存抖动的原因:创建了大量的生命周期很短的对象。
1.1.2 导致的问题:在用户看来程序出现卡顿的现象。
2. 内存抖动开发环境监控
- 通过Android studio的profile可以发现内存抖动的问题,具体操作为在profile中如果发现锯齿状(图中红框1)或者下面出现了大量的垃圾框(红框2)则说明出现了内存抖动的问题,如图1。
3. 内存抖动防范
-
避免频繁的装箱和拆箱,如ava中基本数据类型
-127> int >127
会被转成对象类型。 -
避免在自定义控件的onMeasure,onLayout,onDraw方法中创建对象因为这些方法会频繁的调用,如果在他们方法体内创建对象,由于方法执行完成后就会回收局部变量,因此会导致频繁的回收,通过定义全局变量,在函数中重置对象的属性是来时对应的对象。
-
在使用字符串拼接时,不要使用
+(加号)
进行拼接,因为通过加号
拼接的方式会产生大量的对象,这也会导致频繁的内存回收。
4. 源码中如何解决频繁创建对象的问题?
在使用Handler的时候,通过handler的sendmessage方法发送消息,如果频繁的发送消息是否是也需要创建大量的Message对象?在系统中Message可以通过Message.obtain() 方法获得Message对象,查看Message的源码可知Message内部有一个.next
的变量,Message提供了obtain
和release
两个方法。Message通过维护了一个50个大小的对象池来避免创建大量生命周期短的对象避免频繁gc。
5. 总结
- 避免创建太多生命周期太短的对象。
- 通过as的profile可以发现内存抖动问题。
- 如果需要频繁创建生命周期很短的对象可以使用对象池的方式避免。
为了帮助到大家更好的掌握性能优化相关知识点,这准备了性能优化知识点汇总的学习文档,中间记录了 启动优化、内存优化、UI优化……等知识点,可谓是很全面了,有需要的可以通过以下↓↓↓进行参考学习!
有需要的可以复制下方链接,传送直达!!!
https://qr21.cn/CaZQLo?BIZ=ECOMMERCE
网友评论