Android内存管理

本文深入探讨了Android系统的内存回收机制,特别是Low Memory Killer如何决定进程回收。介绍了应用程序如何在onLowMemory和onTrimMemory方法中进行响应,以降低被系统回收的可能性。此外,还讨论了不同级别内存通知的调用时机以及如何在组件中实现内存优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 本部分将分两部分来讲解。

    1、android 内存回收机制,即采用了 Low Memory Killer。

    2、正对Low Memory Killer回收机制,那么应用程序需要在 onLowMemory 和 onTrimMemory 方法中怎么处理,来降低系统对APP进程的回收率。

  • 第二步;MIUI、华为等非原生系统,第三方软件等,将APP杀死之后,APP的重启方式。
    详见:https://blog.csdn.net/wangqiubo2010/article/details/79619996

一、android 进程回收机制。

  1. AMS 和 Low Memory Killer 之间的通讯。
    a、进程的回收 是通过进程的重要程度机制来确定回收的,重要的程度低的并且内存占用大的会最先被回收。
    b、因此当收到进程需要回收通告的时候,可以在 onLowMemory 和 onTrimMemory中对本APP某些占用内存比较大的进行清除,以降低APP进程被杀死的概率。
    c、进程的重要程度,是AMS来计算得到的,即是 oom_adj,本变量代表了一个进程的重要程度。
    d、 Low Memory Killer 是linux系统中的,它只知道每个APP所占用的内存大小,但是并参与 oom_adj 的计算,因此当要发生GC防止OOM, Low Memory Killer 和 AMS进行通讯,AMS根据计算得到的oom_adj传送给了Low Memory Killer,Low Memory Killer 通过 oom_adj 来杀死 oom_adj( 值越大重要程度越低) 比较高的,并且占用内存比较大的进程,从而释放内存。
    d、oom_adj中,重要程度排列依次为 前台进程(Forgroud process,oom_adj = 0)、可见进程(Visible Process,oom_adj = 1 ),服务进程(Service process)、后台进程(Background process)、空进程(Empty process)
    e、oom_adj 进程值及其注解见下图。
    这里写图片描述

f、oom_adj 的值源码在放在ProcessList.java中,以下源码是android 25中的,可能版本不一样,在android 25中该值已经发生了变化,如下:

  // Uninitialized value for any major or minor adj fields
    static final int INVALID_ADJ = -10000;

    // Adjustment used in certain places where we don't know it yet.
    // (Generally this is something that is going to be cached, but we
    // don't know the exact value in the cached range to assign yet.)
    static final int UNKNOWN_ADJ = 1001;

    // This is a process only hosting activities that are not visible,
    // so it can be killed without any disruption.
    static final int CACHED_APP_MAX_ADJ = 906;
    static final int CACHED_APP_MIN_ADJ = 900;

    // The B list of SERVICE_ADJ -- these are the old and decrepit
    // services that aren't as shiny and interesting as the ones in the A list.
    static final int SERVICE_B_ADJ = 800;

    // This is the process of the previous application that the user was in.
    // This process is kept above other things, because it is very common to
    // switch back to the previous app.  This is important both for recent
    // task switch (toggling between the two top recent apps) as well as normal
    // UI flow such as clicking on a URI in the e-mail app to view in the browser,
    // and then pressing back to return to e-mail.
    static final int PREVIOUS_APP_ADJ = 700;

    // This is a process holding the home application -- we want to try
    // avoiding killing it, even if it would normally be in the background,
    // because the user interacts with it so much.
    static final int HOME_APP_ADJ = 600;

    // This is a process holding an application service -- killing it will not
    // have much of an impact as far as the user is concerned.
    static final int SERVICE_ADJ = 500;

    // This is a process with a heavy-weight application.  It is in the
    // background, but we want to try to avoid killing it.  Value set in
    // system/rootdir/init.rc on startup.
    static final int HEAVY_WEIGHT_APP_ADJ = 400;

    // This is a process currently hosting a backup operation.  Killing it
    // is not entirely fatal but is generally a bad idea.
    static final int BACKUP_APP_ADJ = 300;

    // This is a process only hosting components that are perceptible to the
    // user, and we really want to avoid killing them, but they are not
    // immediately visible. An example is background music playback.
    static final int PERCEPTIBLE_APP_ADJ = 200;

    // This is a process only hosting activities that are visible to the
    // user, so we'd prefer they don't disappear.
    static final int VISIBLE_APP_ADJ = 100;
    static final int VISIBLE_APP_LAYER_MAX = PERCEPTIBLE_APP_ADJ - VISIBLE_APP_ADJ - 1;

    // This is the process running the current foreground app.  We'd really
    // rather not kill it!
    static final int FOREGROUND_APP_ADJ = 0;

    // This is a process that the system or a persistent process has bound to,
    // and indicated it is important.
    static final int PERSISTENT_SERVICE_ADJ = -700;

    // This is a system persistent process, such as telephony.  Definitely
    // don't want to kill it, but doing so is not completely fatal.
    static final int PERSISTENT_PROC_ADJ = -800;

    // The system process runs at the default adjustment.
    static final int SYSTEM_ADJ = -900;

    // Special code for native processes that are not being managed by the system (so
    // don't have an oom adj assigned by the system).
    static final int NATIVE_ADJ = -1000;

二、命令行对进程信息的分析。

  1. 保证电脑上adb可以使用,如果adb 提示 “不是命令”,环境配置 Path中增加 adb地址,例如:D:\develop tool\sdk\platform-tools
  2. 命令按照以下顺序执行:
    a、adb shell
    b、 dumsys meminfo
    执行以上命令行之后,则输出结果如下:
    这里写图片描述

通过以上截图,可以知道,我当前的app是交互的APP。

c、dumsys meminfo com.uuch.android_zxinglibrary ;查看本进程的详细信息,截图如下:
这里写图片描述

以上截图对本APP的详细信息进行了介绍,并且设计性能分析情况也有了说明。

三、onLowMemory 和 onTrimMemory详解。
通过以上分析知道了android对于进行的回收策略是 LowMemoryKiller,具体的思想是当内存吃紧需要进行进程回收的时候,则LowMemoryKiller 会最先把进程的oom_adj 值高(重要程度低),占用内存高的进程进行回收。回收之前AMS会发送信息,调用 onLowMemory 和 onTrimMemory。因此,通过在 onLowMemory 和 onTrimMemory中对本进程的某些内存进行一部分释放,则可以降低被kill的概率,提高存活率。例如, onLowMemory 和 onTrimMemory 对占用内存比较高的Bitmap进行清理,回来的时候再进行加载。

  1. onLowMemory 是 ComponentCallbacks 接口中的方法,onTrimMemory(int level) 是 ComponentCallbacks2 接口中的方法,onTrimMemory 是在4.0之后增加的。
  2. onLowMemory 的调用时机是,当后台线程全部被杀死之后,则调用onLowMemory (),也就是当最后一个后台线程别杀死之后,则onLowMemory 会被调用。
  3. onTrimMemory(int level),则在后台线程有无情况下,都有可能被调用,具体看定义的策略,也就是参数level的定义。
  4. onLowMemory 、onTrimMemory在以下组件中存在,同时也可以自定义即是实现ComponentCallbacks 和 ComponentCallbacks2 并注册。
    Activity、service、Fragment、ContentProvider、Application。

  5. onTrimMemory(int level),调用策略的分类,见ComponentCallbacks2 的定义。
    a、TRIM_MEMORY_COMPLETE,内存不足时,当本进程是后台进程列表中的最后一个进程时 才调用。
    b、TRIM_MEMORY_MODERATE,内存不足时,当本进程存在于后台进程列表中间的时候就调用。
    c、TRIM_MEMORY_BACKGROUND,内存不足时,本进程后台进程的时候就调用,无论其位置在后台进程列表哪个位置,只要触发了就调用。
    e、TRIM_MEMORY_RUNNING_CRITICAL,内存不足,并且后台进程不足3个,该进程优先级比较高则调用。
    f、TRIM_MEMORY_RUNNING_LOW,内存不足,并且后台进程不足5个,该进程优先级比较低则调用。
    g、TRIM_MEMORY_RUNNING_MODERATE:内存不足(后台进程超过5个),并且该进程优先级比较高,需要清理内存。
    h、TRIM_MEMORY_UI_HIDDEN,内存不足,并且UI如果已经隐藏,则调用清理资源。

见下图:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值