• 疑问

    不知道题主是从哪里获取到的 oom_adj 和进程的对应关系,从翻看 Android 源码的结果来看,大部分是和你总结的对应不上的。

    oom_adj 的意义

    翻看源代码可以得到如下信息

    // OOM adjustments for processes in various states:
    
     // 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 = 16;
    
     // 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;
    

    可以看到 oom_adj=4 的进程是系统尽量保护的进程。

    lowmemorykiller 实现原理

    这里给出 lowmemorykiller 的源码,题主可以去看看它的实现
    https://android.googlesource.com/kernel/common.git/+/android-3.4/drivers/staging/android/lowmemorykiller.c

    精力有限,暂时看了这些源码,有兴趣的可以一起学习交流。

  • FaceBook/infer 试玩合集 at 2016年01月26日

    使用源码安装的整个过程没有报错,在执行的时候也出现这个错误:

    Failed to run InferAnalyze binary, exiting
    

    Google 解决方案大部分反馈结果如下:

    About the "Failed to run InferAnalyze binary, exiting" error, you have to compile the binaries of Infer first, please follow the instructions here.

    上面的结果让我们先编译 infer 二进制源码,很奇怪,我们其实进行源码安装的时候已经编译过了,而且没有报错
    按照上面的方式重新执行错误结果一致。
    回头想想,为什么大部分结果会让我们回去编译?
    重新翻看 Facebook 给出的官方文档,我们发现大部分该执行的命令都已经执行过了,但是有个比较陌生的插件opam,它是单独安装的。
    会不会是它有所依赖呢?
    顺着这个思路很自然在官方文档中找到了下面这段话

    Install Infer from source without opam

    If for some reason you prefer to install Infer's OCaml dependencies by some means other than opam, you can still compile Infer by running:

    ./autogen.sh
    ./configure
    make # or make java
    # Install Infer into your PATH
    export PATH=`pwd`/infer/bin:$PATH
    

    执行上述脚本,注意执行./configure 程序报错了,但是结果有很明显的提示让你执行:

    opam pin add --yes --no-action .
    opam install --deps-only infer
    

    顺着提示继续执行,发现执行 opam install --deps-only infer 命令的时候又出错了,但是它依然很人性化的提示你执行下列脚本:

    opam depext camlp4.4.01+system
    

    执行上述脚本后,将之前执行失败的脚本重新执行,不再出现报错了。
    最后 make 编译会执行很长时间,等编译完成后就可以顺利执行 infer 静态检测内存泄露和空指针异常了。

    注:在我的 unbuntu 机器上直接 make 会报错,因为我只关注 Android 项目,所以执行的是 make java,这样一切正常,现在正在跑项目中。暂时未研究是什么原因导致的,有兴趣的可以一起去研究讨论。

  • 公司用 windows+Linux,个人用 mac,怎么选好呢?