Android——内存管理-lowmemorykiller 机制

  前段时间碰到一个apk多个process依次开跑,跑到最后一个process的时候,第一个process给kill掉了,虽然第一个process中含有broadcast receive,被kill掉的原因是由于触发到了lowmemorykiller,这样一来apk最后的结果就异常了~ 尝试再三 规避掉了这个问题,记录一下~

撰写不易,转载需注明出处:http://blog.csdn.net/jscese/article/details/47317765本文来自 【jscese】的博客!

概念

andorid用户层的application process ,在各种activity生命周期切换时,会触发AMS中的回收机制,比如启动新的apk,一直back 退出一个apk,在5.1上的代码来看,除了android AMS中默认的回收机制外,还会去维护一个oom adj 变量,作为linux层 lowmemorykiller的参考依据。

AMS回收机制

入口为trimApplications() 可以发现很多地方有调用,stop unregisterreceiver之类的操作时都会去触发回收:

    final void trimApplications() {
        synchronized (this) {
            int i;

            // First remove any unused application processes whose package
            // has been removed.
            for (i=mRemovedProcesses.size()-1; i>=0; i--) {
                final ProcessRecord app = mRemovedProcesses.get(i);
                if (app.activities.size() == 0
                        && app.curReceiver == null && app.services.size() == 0) {
                    Slog.i(
                        TAG, "Exiting empty application process "
                        + app.processName + " ("
                        + (app.thread != null ? app.thread.asBinder() : null)
                        + ")\n");
                    if (app.pid > 0 && app.pid != MY_PID) {
                        app.kill("empty", false);
                    } else {
                        try {
                            app.thread.scheduleExit();
                        } catch (Exception e) {
                            // Ignore exceptions.
                        }
                    }
                    cleanUpApplicationRecordLocked(app, false, true, -1);
                    mRemovedProcesses.remove(i);

                    if (app.persistent) {
                        addAppLocked(app.info, false, null /* ABI override */);
                    }
                }
            }

            // Now update the oom adj for all processes.

            updateOomAdjLocked();

        }
    }

mRemovedProcesses 列表中主要包含了 crash 的进程、5 秒内没有响应并被用户选在强制关闭的进程、以及应用开发这调用 killBackgroundProcess 想要杀死的进程。调用 Process.killProcess 将所有此类进程全部杀死。

updateOomAdjLocked 计算更新所有process的 oomadj

继续看:

final void updateOomAdjLocked() {
...
        // First update the OOM adjustment for each of the
        // application processes based on their current state.
        int curCachedAdj = ProcessList.CACHED_APP_MIN_ADJ;
        int nextCachedAdj = curCachedAdj+1;
        int curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ;
        int nextEmptyAdj = curEmptyAdj+2;
        for (int i=N-1; i>=0; i--) {
            ProcessRecord app = mLruProcesses.get(i);
            if (!app.killedByAm && app.thread != null) {
                app.procStateChanged = false;
                computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now);
    ...
     applyOomAdjLocked(app, TOP_APP, true, now);
    ...
      }
      ...
     }
...

}

computeOomAdjLocked 计算当前process的adj,详细规则就不贴了,大体会根据 top activity .receiver.service process state 一大堆相关的因素去得出一个adj值。

adj 值 (-17 ~15) 越小优先级越高,从注释能看出来,策略在kernel中的lowmemorykiller驱动中实现

这里看下定义 在\frameworks\base\services\core\java\com\android\server\am\ProcessList.java :

    // 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 = 15;
    static final int CACHED_APP_MIN_ADJ = 9;

    // 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 = 8;

    // 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 = 7;

    // 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 = 6;

    // 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 = 5;

    // 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 = 4;

    // 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 = 3;

    // 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 = 2;

    // 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 = 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 = -11;

    // 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 = -12;

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

    // 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 = -17;

applyOomAdjLocked 将上面计算好的adj值经过一定的修整,设置到对应的process。

只关注跟lowmemorykiller 相关的调用接口, 省略了AMS中自己根据PROCESS_STATE的 kill策略, 大体有如下:

必须是非 persistent 进程,即非系统进程;

必须是空进程,即进程中没有任何 activity 存在。如果杀死存在 Activity 的进程,有可能关闭用户正在使用的程序,或者使应用程序恢复的时延变大,从而影响用户体验;

必须无 broadcast receiver。运行 broadcast receiver 一般都在等待一个事件的发生,用户并不希望此类程序被系统强制关闭;

进程中 service 的数量必须为 0。存在 service 的进程很有可能在为一个或者多个程序提供某种服务,如 GPS 定位服务。杀死此类进程将使其他进程无法正常服务。

看下 applyOomAdjLocked中的核心:

    private final boolean applyOomAdjLocked(ProcessRecord app,
            ProcessRecord TOP_APP, boolean doingAll, long now) {
...

        if (app.curAdj != app.setAdj) {
            ProcessList.setOomAdj(app.pid, app.info.uid, app.curAdj);
            if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
                TAG, "Set " + app.pid + " " + app.processName +
                " adj " + app.curAdj + ": " + app.adjType);
            app.setAdj = app.curAdj;
        }
...

}

设置oomadj ,继续看 ProcessList.java

    /**
     * Set the out-of-memory badness adjustment for a process.
     *
     * @param pid The process identifier to set.
     * @param uid The uid of the app
     * @param amt Adjustment value -- lmkd allows -16 to +15.
     *
     * {@hide}
     */
    public static final void setOomAdj(int pid, int uid, int amt) {
        if (amt == UNKNOWN_ADJ)
            return;

        long start = SystemClock.elapsedRealtime();
        ByteBuffer buf = ByteBuffer.allocate(4 * 4);
        buf.putInt(LMK_PROCPRIO);
        buf.putInt(pid);
        buf.putInt(uid);
        buf.putInt(amt);
        writeLmkd(buf);
        long now = SystemClock.elapsedRealtime();
        if ((now-start) > 250) {
            Slog.w("ActivityManager", "SLOW OOM ADJ: " + (now-start) + "ms for pid " + pid
                    + " = " + amt);
        }
    }

writeLmkd 写process pid uid 以及adj 的buf, 以一个定义command打头

    private static void writeLmkd(ByteBuffer buf) {

        for (int i = 0; i < 3; i++) {
            if (sLmkdSocket == null) {
                    if (openLmkdSocket() == false) {
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException ie) {
                        }
                        continue;
                    }
            }

            try {
                sLmkdOutputStream.write(buf.array(), 0, buf.position());
                return;
            } catch (IOException ex) {
                Slog.w(ActivityManagerService.TAG,
                       "Error writing to lowmemorykiller socket");

                try {
                    sLmkdSocket.close();
                } catch (IOException ex2) {
                }

                sLmkdSocket = null;
            }
        }
    }
}

可以看到try了3次 ,去打开对应的socket 然后写数据,openLmkdSocket 实现如下,android的 LocalSocket 机制,通过lmkd 这个socket通信

sLmkdSocket = new LocalSocket(LocalSocket.SOCKET_SEQPACKET);
            sLmkdSocket.connect(
                new LocalSocketAddress("lmkd",
                        LocalSocketAddress.Namespace.RESERVED));
            sLmkdOutputStream = sLmkdSocket.getOutputStream();

这是作为client去请求connect ,而service端的处理在 \system\core\lmkd\lmkd.c , 可以看下这个service的启动:

service lmkd /system/bin/lmkd
    class core
    critical
    socket lmkd seqpacket 0660 system system


标准的 C/S模式,AMS中发起的通信command 开头种类,以及buf格式 如下:

    // LMK_TARGET <minfree> <minkillprio> ... (up to 6 pairs)
    // LMK_PROCPRIO <pid> <prio>
    // LMK_PROCREMOVE <pid>
    static final byte LMK_TARGET = 0;
    static final byte LMK_PROCPRIO = 1;
    static final byte LMK_PROCREMOVE = 2;

设置单一process 用的是 LMK_PROCPRIO

设置整个LMK adj minfree策略的是 LMK_TARGET

LMK_PROCREMOVE kill process用


lmkd service

这个service 的代码比较短 1K不到,机制也比较简单:

int main(int argc __unused, char **argv __unused) {
    struct sched_param param = {
            .sched_priority = 1,
    };

    mlockall(MCL_FUTURE);
    sched_setscheduler(0, SCHED_FIFO, &param);
    if (!init())
        mainloop();

    ALOGI("exiting");
    return 0;
}

init 那些socket相关,注册event handle func ,最后跳到mainloop去 循环poll等待

 ctrl_lfd = android_get_control_socket("lmkd");
    if (ctrl_lfd < 0) {
        ALOGE("get lmkd control socket failed");
        return -1;
    }

细节不做关注,直接看收到刚刚 AMS那边发过来的command buf 的处理:

static void ctrl_command_handler(void) {
    int ibuf[CTRL_PACKET_MAX / sizeof(int)];
    int len;
    int cmd = -1;
    int nargs;
    int targets;

    len = ctrl_data_read((char *)ibuf, CTRL_PACKET_MAX);
    if (len <= 0)
        return;

    nargs = len / sizeof(int) - 1;
    if (nargs < 0)
        goto wronglen;

    cmd = ntohl(ibuf[0]);

    switch(cmd) {
    case LMK_TARGET:
        targets = nargs / 2;
        if (nargs & 0x1 || targets > (int)ARRAY_SIZE(lowmem_adj))
            goto wronglen;
        cmd_target(targets, &ibuf[1]);
        break;
    case LMK_PROCPRIO:
        if (nargs != 3)
            goto wronglen;
        cmd_procprio(ntohl(ibuf[1]), ntohl(ibuf[2]), ntohl(ibuf[3]));
        break;
    case LMK_PROCREMOVE:
        if (nargs != 1)
            goto wronglen;
        cmd_procremove(ntohl(ibuf[1]));
        break;
    default:
        ALOGE("Received unknown command code %d", cmd);
        return;
    }

    return;

wronglen:
    ALOGE("Wrong control socket read length cmd=%d len=%d", cmd, len);
}

先看上面对应的LMK_PROCPRIO 设置某个process 的adj ,核心如下:

    snprintf(path, sizeof(path), "/proc/%d/oom_score_adj", pid);
    snprintf(val, sizeof(val), "%d", lowmem_oom_adj_to_oom_score_adj(oomadj));
    writefilestring(path, val);

直接写process对应的文件节点,传下来的adj值 做了一个转换再写进 oom_score_adj:

static int lowmem_oom_adj_to_oom_score_adj(int oom_adj)
{
    if (oom_adj == OOM_ADJUST_MAX) //15
        return OOM_SCORE_ADJ_MAX; //1000
    else
        return (oom_adj * OOM_SCORE_ADJ_MAX) / -OOM_DISABLE;//-17
}

kernel驱动中process manager 会有对应的处理机制 ,转换后个oom_score_adj保存在进程结构体 kernel\include\linux\sched.h

task_struct->signal_struct->short oom_score_adj; /* OOM kill score adjustment */


lowmemorykiller driver

kernel中的支持:

autoconf.h中

#define CONFIG_ANDROID_LOW_MEMORY_KILLER 1

可自行到kernel中 make menuconfig 查看

驱动目录:\kernel\drivers\staging\android\lowmemorykiller.c

static int __init lowmem_init(void)
{
    register_shrinker(&lowmem_shrinker);
    return 0;
}

#ifdef CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES
__module_param_call(MODULE_PARAM_PREFIX, adj,
            &lowmem_adj_array_ops,
            .arr = &__param_arr_adj,
            S_IRUGO | S_IWUSR, -1);
__MODULE_PARM_TYPE(adj, "array of short");
#else
module_param_array_named(adj, lowmem_adj, short, &lowmem_adj_size,
             S_IRUGO | S_IWUSR);
#endif
module_param_array_named(minfree, lowmem_minfree, uint, &lowmem_minfree_size,
             S_IRUGO | S_IWUSR);

注册了一个shrinker ,这个机制之前没接触过,大体的意义就是向系统注册了这个shrinker 回调函数之后,当系统空闲内存页面不足时会调用。

CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES 支持动态改 策略阀门 值。

另外注册了文件ops 以及节点 adj .minfree 分别与lowmem_adj . lowmen_minfree 数组成对应关系

策略数组以及阀值,两个数组之间也是一一对应关系,当内存小于64M时 就去准备 kill adj >=12 的process,取最低优先级 先kill, 比如此时有3个进程分别为 12 12 14 ,那么首先kill掉的是 14 ,kill之后还是少于64M 那么两个12 adj之间,先杀占用高的,这个函数实现在下面的 lowmem_shrink 中。

static short lowmem_adj[6] = {
    0,
    1,
    6,
    12,
};
static int lowmem_adj_size = 4;
static int lowmem_minfree[6] = {
    3 * 512,    /* 6MB */
    2 * 1024,   /* 8MB */
    4 * 1024,   /* 16MB */
    16 * 1024,  /* 64MB */
};

先看下处理函数 lowmem_shrinker:

static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
{
    struct task_struct *tsk;
    struct task_struct *selected = NULL;
    int rem = 0;
    int tasksize;
    int i;
    short min_score_adj = OOM_SCORE_ADJ_MAX + 1;
    int minfree = 0;
    int selected_tasksize = 0;
    short selected_oom_score_adj;
    int array_size = ARRAY_SIZE(lowmem_adj);
    int other_free = global_page_state(NR_FREE_PAGES) - totalreserve_pages;
    int other_file = global_page_state(NR_FILE_PAGES) -
                        global_page_state(NR_SHMEM);

    if (lowmem_adj_size < array_size)
        array_size = lowmem_adj_size;
    if (lowmem_minfree_size < array_size)
        array_size = lowmem_minfree_size;
    for (i = 0; i < array_size; i++) {
    //依次遍历策略阀值数组,从小到大,根据当前memory free情况,取触发adj值
        minfree = lowmem_minfree[i];
        if (other_free < minfree && other_file < minfree) {
            min_score_adj = lowmem_adj[i];
            break;
        }
    }
//这里得到的min_score_adj  就是此时内存状态下 将会kill掉的最小score_adj
...
for_each_process(tsk) {
...
tasksize = get_mm_rss(p->mm);
...
        if (selected) {
            if (oom_score_adj < selected_oom_score_adj)
                continue;
            if (oom_score_adj == selected_oom_score_adj &&
                tasksize <= selected_tasksize)
                continue;
        }//可以看到 遍历一圈process 只为找到一个 oom_score_adj tasksize 最大的process
        selected = p;
        selected_tasksize = tasksize;
        selected_oom_score_adj = oom_score_adj;
  }
    if (selected) {
        lowmem_print(1, "Killing ‘%s‘ (%d), adj %hd,\n"                 "   to free %ldkB on behalf of ‘%s‘ (%d) because\n"                 "   cache %ldkB is below limit %ldkB for oom_score_adj %hd\n"                 "   Free memory is %ldkB above reserved\n",
                 selected->comm, selected->pid,
                 selected_oom_score_adj,
                 selected_tasksize * (long)(PAGE_SIZE / 1024),
                 current->comm, current->pid,
                 other_file * (long)(PAGE_SIZE / 1024),
                 minfree * (long)(PAGE_SIZE / 1024),
                 min_score_adj,
                 other_free * (long)(PAGE_SIZE / 1024));

        trace_lowmem_kill(selected,  other_file, minfree, min_score_adj, other_free);

        lowmem_deathpending_timeout = jiffies + HZ;
        send_sig(SIGKILL, selected, 0);  //发送kill signal 去kill selected的process
        set_tsk_thread_flag(selected, TIF_MEMDIE);
        rem -= selected_tasksize;
    }
}

以上就是正常的依次 触发lowmemorykill 回收策略流程,驱动比较灵活,还提供了策略阀门值动态修改的机制,通过file ops 让application层去写入修改。

上面有贴出文件节点代码 分别对应为 adj minfree

实际路径为:

同样application 那边设置下来的话 也是需要通过 lowmem_oom_adj_to_oom_score_adj 去转换之后 赋值到 策略数组 lowmem_adj 中,需要注意的是 driver中定义的数组size 为 6 。

application层的接口还是放在上面说到过的 ProcessList.java 中,贴出相关的定义和函数吧,具体流程还是得看代码:

    // These are the various interesting memory levels that we will give to
    // the OOM killer.  Note that the OOM killer only supports 6 slots, so we
    // can‘t give it a different value for every possible kind of process.
    private final int[] mOomAdj = new int[] {
            FOREGROUND_APP_ADJ, VISIBLE_APP_ADJ, PERCEPTIBLE_APP_ADJ,
            BACKUP_APP_ADJ, CACHED_APP_MIN_ADJ, CACHED_APP_MAX_ADJ
    };
    // These are the low-end OOM level limits.  This is appropriate for an
    // HVGA or smaller phone with less than 512MB.  Values are in KB.
    //ActionsCode(authro:songzhining, comment: increase oom free mem for 5.0)
    private final int[] mOomMinFreeLow = new int[] {
            12288, 18432, 24576, /*8192, 12288, 16384,*/
            36864, 43008+20000, 49152+20000 /*36864, 43008, 49152*/
    };
    // These are the high-end OOM level limits.  This is appropriate for a
    // 1280x800 or larger screen with around 1GB RAM.  Values are in KB.
    //ActionsCode(authro:songzhining, comment: increase oom free mem for 5.0)
    private final int[] mOomMinFreeHigh = new int[] {
            73728, 92160, 110592, /*32768, 61440, 73728,*/
            129024, 147456+20000, 184320+20000 /*129024, 147456, 184320*/
    };

    // The actual OOM killer memory levels we are using.
    private final int[] mOomMinFree = new int[mOomAdj.length];

上面为定义的 策略adj 以及minfree 相关的数组资源

  private void updateOomLevels(int displayWidth, int displayHeight, boolean write) {
  ...
          if (write) {
            ByteBuffer buf = ByteBuffer.allocate(4 * (2*mOomAdj.length + 1));
            buf.putInt(LMK_TARGET);
            for (int i=0; i<mOomAdj.length; i++) {
                buf.putInt((mOomMinFree[i]*1024)/PAGE_SIZE);
                buf.putInt(mOomAdj[i]);
            }

            writeLmkd(buf);
            SystemProperties.set("sys.sysctl.extra_free_kbytes", Integer.toString(reserve));
        }// 同上面提到的setoomadj 一样,最终的设置由lmkd service 去实现
}

lmkd service 中对应的command LMK_TARGET 函数为:

static void cmd_target(int ntargets, int *params) {
...
        for (i = 0; i < lowmem_targets_size; i++) {
            char val[40];

            if (i) {
                strlcat(minfreestr, ",", sizeof(minfreestr));
                strlcat(killpriostr, ",", sizeof(killpriostr));
            }

            snprintf(val, sizeof(val), "%d", lowmem_minfree[i]);
            strlcat(minfreestr, val, sizeof(minfreestr));
            snprintf(val, sizeof(val), "%d", lowmem_adj[i]);
            strlcat(killpriostr, val, sizeof(killpriostr));
        }

        writefilestring(INKERNEL_MINFREE_PATH, minfreestr);
        writefilestring(INKERNEL_ADJ_PATH, killpriostr);
        // 获取了上面processlist 里面传下来的两个 策略数组  然后write到文件节点中
        //#define INKERNEL_MINFREE_PATH "/sys/module/lowmemorykiller/parameters/minfree"
        //#define INKERNEL_ADJ_PATH "/sys/module/lowmemorykiller/parameters/adj"
        //驱动中对应的 文件节点
}

大体脉络理清,运行机制也清晰了,具体的实现细节就需要细读code了

而我碰到的问题,就是memory 不足 触发了lowmemorykiller,但是运行的apk 多进程时 ,最初的进程已经进入后台,compute adj 优先级较低,此时新开进程申请memory,触发回收,memory free 达到lowmemorykill的阀值,直接就杀掉了正在运行apk的后台进程, 不管有没有receiver ,service 而apk如有依赖性 就会触发异常了。

从另一层面上来说,multi process 的apk 对lowmemory device的兼容性存在缺陷,设计并不合理。

作为平台需求,只能从系统的方面来规避了,强提特定的process 的adj 以达到正常运行,但这只是规避~不符合规范

从最近的一些工作来看,碰到了好几次这种存在兼容性问题的apk ,上一篇 32bit/64bit 平台apk动态库的问题 也是这种现象,这还都是 google play 上的apk ,apk的门槛越来越低,都是一味的去追求屌绚酷 ,对深层次的运行机制不去关注,稳定以及运行兼容性自然无法达标,当然这也可以算是google在平台框架兼容性上存在漏洞,这也是android 永远无法追上apple的一个原因之一吧~ 个人吐槽~请笑看

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-01 03:28:46

Android——内存管理-lowmemorykiller 机制的相关文章

Android 内存管理机制详解

??嵌入式设备的一个普遍特点是内存容量相对有限.当运行的程序超过一定数量时,或者涉及复杂的计算时,很可能出现内存不足,进而导致系统卡顿的现象.Android 系统也不例外,它同样面临着设备物理内存短缺的困境.对于已经启动过一次的Android程序,再一次启动所花的时间会明显减少.原因在于Android系统并不马上清理那些已经"淡出视野"的程序(比如你调用Activity.finish退出UI界面).它们在一定的时间里仍然驻留在内存中.这样做的好处是明显的,即下一次启动不需要再为程序重新

Android内存管理机制详解 (zhuan)

http://www.2cto.com/kf/201212/175786.html 与windows内存区别 在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,在这方面,区别于 Windows的内存管理.主要特点是,无论物理内存有多大,Linux都将其充份利用,将一些程序调用过的硬盘数据读入内存,利用内存读写的高速特性来提高Linux系统的数据访问性能.而Windows是只在需要内存时,才为应用程序分配内存,

[Android Memory] Android内存管理、监测剖析

转载自:http://blog.csdn.net/anlegor/article/details/23398785 Android内存管理机制: Android内存管理主要有:LowMemory Killer机制,Ashmem,PMEM/ION及Native内存和Dalvik内存管理管理和JVM垃圾回收机制. LowMemory Killer机制: 源码位置drivers/staging/Android/lowmemorykiller.c Android是一个多任务系统,也就是说可以同时运行多个

Android内存管理之道

相信一步步走过来的Android从业者,每个人都会遇到OOM的情况.如何避免和防范OOM的出现,对于每一个程序员来说确实是一门必不可少的能力.今天我们就谈谈在Android平台下内存的管理之道,开始今天的主题之前,先再次回顾两个概念. 内存泄漏:对象在内存heap堆中中分配的空间,当不再使用或没有引用指向的情况下,仍不能被GC正常回收的情况.多数出现在不合理的编码情况下,比如在Activity中注册了一个广播接收器,但是在页面关闭的时候进行unRegister,就会出现内存溢出的现象.通常情况下

Android 电源管理 -- wakelock机制

转载地址:http://blog.csdn.net/wh_19910525/article/details/8287202 Wake Lock是一种锁的机制, 只要有人拿着这个锁,系统就无法进入休眠, 可以被用户态程序和内核获得. 这个锁可以是有超时的 或者 是没有超时的, 超时的锁会在时间过去以后自动解锁.如果没有锁了或者超时了, 内核就会启动休眠的那套机制来进入休眠. PowerManager.WakeLock 有加锁和解锁两种状态,加锁的方式有两种: 第一种是永久的锁住,这样的锁除非显式的

JVM内存管理的机制

1.JVM内存管理的机制 内存空间划分为:Sun JDK在实现时遵照JVM规范,将内存空间划分为堆.JVM方法栈.方法区.本地方法栈.PC寄存器. 堆: 堆用于存储对象实例及数组值,可以认为Java中所有通过new创建的对象的内存都在此分配,Heap中对象所占用的内存由GC进行回收,在32位操作系统上最大为2GB,在64位操作系统上则没有限制,其大小可通过-Xms和-Xmx来控制,-Xms为JVM启动时申请的最小Heap内存,默认为物理内存的1/64但小于1GB:-Xmx为JVM可申请的最大He

android 内存管理研究

1. 内存管理基础知识 http://www.cnblogs.com/xingfuzzhd/p/3485924.html   1. mImageView.setImageResource(R.drawable.my_image); 这段代码会调用 BitmapFactory.decodeStream() 生成一个 Bitmap.所以不要以为它比自己创建 Bitmap 节省内存. 3.  实际测试: 我使用了多种调用图片的方法来测试: 第一种: // 直接载入资源 idImageView imag

Android内存管理的原理--进程管理

Android内存管理的原理--进程管理 Android采取了一种有别于 Linux 的进程管理策略,有别于Linux的在进程活动停止后就结束该进程,Android把这些进程都保留在内存中,直到系统需要更多内存为止.这些保留在内存中的进程通常情况下不会影响整体系统的运行速度,并且当用户再次激活这些进程时,提升了进程的启动速度. 那Android什么时候结束进程?结束哪个进程呢? 之前普遍的认识是Android是依据一个名为LRU(last recently used 最近使用过的程序)列表,将程

移动端测试===Android内存管理: 理解App的PSS

Android内存管理: 理解App的PSS 原文链接:http://www.littleeye.co/blog/2013/06/11/android-memory-management-understanding-app-pss/ 当在应用程序上运行Little Eye时,在内存视图中,会报告有关应用程序内存的3个重要统计信息. Dalvik内存使用情况,即Java堆消耗的内存量,Native内存,即JVM外部进程使用的内存量. 然后是第三个统计量,被称为"PSS". 什么是PSS?