1、内存占用高导致的问题
- 1、内存泄漏导致OOM崩溃
- 2、界面卡顿,影响用户体验
- 3、高内存耗电,被系统及安全软件警告,容易被卸载或后台关闭
之所以要内存优化为了更好的适应JVM的GC机制,减少对程序的影响(减少卡顿)。
2、JVM 内存模型
Minor GC 使用标记-清除-复制算法,将Eden区和From Survivor区中存活下来的对象复制到 To Survivor区中,然后清空Eden区和From Survivor区,速度快。
Major GC 采用标记-清除-压缩算法,即,先标记无用的对象,然后将存活下来的对象移动,整理碎片,以腾出更大的连续空间。
如下图所示:
3、GC原理及简介
采用是否根节点可访问判断是否需要回收对象,如下图所示
3.1标记清除复制算法
3.2标记清除复制算法
4、GC Reason和Name
<pre class=”hljs undefined” data-original-code=”” reason”=”” data-snippet-id=”ext.fad1dd2cb080f9ce19557e96ccdfb127″ data-snippet-saved=”false” data-codota-status=”done”>
-
-
-
-
-
-
-
-
-
-
-
-
Concurrent partial mark sweep
-
Concurrent sticky mark sweep
-
GC log 示例
04-06 09:41:48.541 5021-5045/com.husor.beibei I/art: Background partial concurrent mark sweep GC freed 22647(1359KB) AllocSpace objects, 5(969KB) LOS objects, 6% free, 53MB/57MB, paused 5.128ms total 68.744ms
5、如何进行内存优化
- 1、消除内存泄漏
- 2、使用高性能编程
- 3、降低程序运行的内存占用
6、常见内存泄漏和高内存占用原因
- 1、慎重使用static变量
- 2、长周期内部类、匿名内部类长时间持有外部类引用导致相关资源无法释放(Handler或者内部线程等)
- 3、BitMap导致内存溢出
- 4、数据库、文件流等没有关闭
- 5、监听器、广播注册后没有及时注销
- 6、Adapter没有使用convertView
- 7、字符串拼接尽量使用StringBuilder或者StringBuffer
- 8、避免内存抖动,例如不要在onDraw中创建对象。
- 9、界面不可见时,停止动画和相关线程
6.1、示例一:
原因:
sBackground, 是一个静态的变量,但是我们发现,我们并没有显式的保存Contex的引用,但是,当Drawable与View连接之后,Drawable就将View设置为一个回调,由于View中是包含Context的引用的,所以,实际上我们依然保存了Context的引用。这个引用链如下:Drawable->TextView->Context
解决办法:
-
*,应该尽量避免static成员变量引用资源耗费过多的实例,比如Context。
-
第二、Context尽量使用Application Context,因为Application的Context的生命周期比较长
-
第三、使用WeakReference代替强引用。比如WeakReference<Context> mContextRef; (已经不推荐)
6.1、示例二:
原因:
Activity退出后,其实例并未被回收。因为OneThread作为非静态内部类还持有BasicActivity的实例。
解决方案:
-
-
2、如果OneThread需要Context实例,使用弱引用保存它。
-
3、如果有必要,在BasicActivity的OnDestroy里面关闭线程
7、内存分析工具
7、1 Android Monitor
** 优点:**
使用简单,直观显示当前app的内存变化
缺点:
无法具体定位内存问题,只能给出内存笼统的变化。
常用于分析内存变化趋势。
7、2 Allocation Tracker
-
-
2、Studio会自动打开文件,里面展示这一段时间内内存的分配情况,可以分析自己的程序哪里内存占用比较高,是否有大量的相同类型的 Object 被分配和释放。如果有,则其可能引起性能问题。
7、3 MAT
步骤:
在android studio 生成dump文件,并转为标准dump。
如下图所示
- 2使用mat分析
- 以内部线程导致内存泄漏为例分析:
1、多次打开该demo,生成dump文件
2、打开MAT工具,选择“File”>>“open heap dump”,打开dump文件
3、打开后在,“Action”里的“Histogram”,然后搜索SecondActivity
7、4LeakCanary 检测内存泄漏