标签: Android 内存

android 内存泄漏出现的情况

    • 非静态内部类的静态实例
      由于内部类默认持有外部类的引用,而静态实例属于类。所以,当外部类被销毁时,内部类仍然持有外部类的引用,致使外部类无法被GC回收。因此造成内存泄露。
    • 类的静态变量持有大数据对象
      静态变量长期维持到大数据对象的引用,阻止垃圾回收。
    • 资源对象未关闭
      资源性对象如Cursor、Stream、Socket,Bitmap,应该在使用后及时关闭。未在finally中关闭,会导致异常情况下资源对象未被释放的隐患。
    • 注册对象未反注册
      我们常常写很多的Listener,未反注册会导致观察者列表里维持着对象的引用,阻止垃圾回收。
    • Handler临时性内存泄露
      Handler通过发送Message与主线程交互,Message发出之后是存储在MessageQueue中的,有些Message也不是马上就被处理的。

    • 内部线程泄露new Thread(){}.start();Java中的Thread有一个特点就是她们都是直接被GC Root所引用,也就是说Dalvik虚拟机对所有被激活状态的线程都是持有强引用,导致GC永远都无法回收掉这些线程对象,除非线程被手动停止并置为null或者用户直接kill进程操作。看到这相信你应该也是心中有答案了吧 : 我在每一个MainActivity中都创建了一个线程,此线程会持有MainActivity的引用,即使退出Activity当前线程因为是直接被GC Root引用所以不会被回收掉,导致MainActivity也无法被GC回收。所以当使用线程时,一定要考虑在Activity退出时,及时将线程也停止并释放掉
    • Context泄露
    • 内部类的创建需要小心,由于内部类会持有外部类对象,不小心就会造成内存泄漏

Android 内存优化简介

1、内存占用高导致的问题

  • 1、内存泄漏导致OOM崩溃
  • 2、界面卡顿,影响用户体验
  • 3、高内存耗电,被系统及安全软件警告,容易被卸载或后台关闭

之所以要内存优化为了更好的适应JVM的GC机制,减少对程序的影响(减少卡顿)。

2、JVM 内存模型

Minor GC 使用标记-清除-复制算法,将Eden区和From Survivor区中存活下来的对象复制到 To Survivor区中,然后清空Eden区和From Survivor区,速度快。

Major GC 采用标记-清除-压缩算法,即,先标记无用的对象,然后将存活下来的对象移动,整理碎片,以腾出更大的连续空间。

如下图所示:

%title插图%num
JVM.png

3、GC原理及简介

采用是否根节点可访问判断是否需要回收对象,如下图所示

%title插图%num
GC.png
3.1标记清除复制算法
%title插图%num
mark-copy.png
3.2标记清除复制算法
%title插图%num
mark-press.png

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”>

  1. Reason
  2. Concurrent—-后台回收内存,不暂停用户线程
  3. Alloc—-当app要申请内存,而堆又快满了的时候,会阻塞用户线程
  4. Explicit—-调用Systemt.gc()等方法的时候触发,一般不建议使用
  5. NativeAlloc—-当native内存有压力的时候触发
  6. Name
  7. Concurrent mark sweep—-全部对象的检测回收
  8. Concurrent partial mark sweep—-部分的检测回收
  9. Concurrent sticky mark sweep—-仅检测上次回收后创
  10. 建的对象,速度快,卡顿少,比较频繁

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、示例一:
%title插图%num
sample1.png

原因:
sBackground, 是一个静态的变量,但是我们发现,我们并没有显式的保存Contex的引用,但是,当Drawable与View连接之后,Drawable就将View设置为一个回调,由于View中是包含Context的引用的,所以,实际上我们依然保存了Context的引用。这个引用链如下:Drawable->TextView->Context

解决办法:

  1. *,应该尽量避免static成员变量引用资源耗费过多的实例,比如Context。
  2. 第二、Context尽量使用Application Context,因为Application的Context的生命周期比较长
  3. 第三、使用WeakReference代替强引用。比如WeakReference<Context> mContextRef; (已经不推荐)
6.1、示例二:
%title插图%num
sample2.png

原因:

Activity退出后,其实例并未被回收。因为OneThread作为非静态内部类还持有BasicActivity的实例。

解决方案:

  1. 1、OneThread改为静态内部类
  2. 2、如果OneThread需要Context实例,使用弱引用保存它。
  3. 3、如果有必要,在BasicActivity的OnDestroy里面关闭线程

7、内存分析工具

7、1 Android Monitor
%title插图%num
util1.png

** 优点:**
使用简单,直观显示当前app的内存变化
缺点:
无法具体定位内存问题,只能给出内存笼统的变化。
常用于分析内存变化趋势。

7、2 Allocation Tracker
%title插图%num
util2.png
  1. 1、选择进程,在合适的实际开始和结束追踪。
  2. 2、Studio会自动打开文件,里面展示这一段时间内内存的分配情况,可以分析自己的程序哪里内存占用比较高,是否有大量的相同类型的 Object 被分配和释放。如果有,则其可能引起性能问题。
7、3 MAT

步骤:

  • 1生成mat文件

在android studio 生成dump文件,并转为标准dump。
如下图所示

%title插图%num
mat1.png
%title插图%num
mat2.png
  • 2使用mat分析
  • 以内部线程导致内存泄漏为例分析:
    1、多次打开该demo,生成dump文件
    2、打开MAT工具,选择“File”>>“open heap dump”,打开dump文件
    3、打开后在,“Action”里的“Histogram”,然后搜索SecondActivity
%title插图%num
mat3.png
  • 3猜测分析原因

    通过上面看到,存在11个SecondActivity的实例,有点诡异。
    选择SecondActivity这一项,然后右键“Merge Shortest Paths to GC Roots ”>>”exclude all phantom/weak/soft etc references..”

%title插图%num
mat4.png
%title插图%num
mat5.png
7、4LeakCanary 检测内存泄漏
leakcanary.png

直接可以通过通知栏看到内存泄露的地方

友情链接: SITEMAP | 旋风加速器官网 | 旋风软件中心 | textarea | 黑洞加速器 | jiaohess | 老王加速器 | 烧饼哥加速器 | 小蓝鸟 | tiktok加速器 | 旋风加速度器 | 旋风加速 | quickq加速器 | 飞驰加速器 | 飞鸟加速器 | 狗急加速器 | hammer加速器 | trafficace | 原子加速器 | 葫芦加速器 | 麦旋风 | 油管加速器 | anycastly | INS加速器 | INS加速器免费版 | 免费vqn加速外网 | 旋风加速器 | 快橙加速器 | 啊哈加速器 | 迷雾通 | 优途加速器 | 海外播 | 坚果加速器 | 海外vqn加速 | 蘑菇加速器 | 毛豆加速器 | 接码平台 | 接码S | 西柚加速器 | 快柠檬加速器 | 黑洞加速 | falemon | 快橙加速器 | anycast加速器 | ibaidu | moneytreeblog | 坚果加速器 | 派币加速器 | 飞鸟加速器 | 毛豆APP | PIKPAK | 安卓vqn免费 | 一元机场加速器 | 一元机场 | 老王加速器 | 黑洞加速器 | 白石山 | 小牛加速器 | 黑洞加速 | 迷雾通官网 | 迷雾通 | 迷雾通加速器 | 十大免费加速神器 | 猎豹加速器 | 蚂蚁加速器 | 坚果加速器 | 黑洞加速 | 银河加速器 | 猎豹加速器 | 海鸥加速器 | 芒果加速器 | 小牛加速器 | 极光加速器 | 黑洞加速 | movabletype中文网 | 猎豹加速器官网 | 烧饼哥加速器官网 | 旋风加速器度器 | 哔咔漫画 | PicACG | 雷霆加速