如何抓获JVM crash的幕后黑手?(三)

来源:互联网 发布:js与jsp交互 编辑:程序博客网 时间:2024/04/29 00:30

      通过前两篇如何抓获JVM crash的幕后黑手?(一) 如何抓获JVM crash的幕后黑手?(二)的分析,如果还不能查到原因,那很有可能不是应用自身的问题,而是系统将应用强行kill了,如何判断是系统强行kill的呢?

      我们需要先了解下linux的一个oom-killer机制。linux oom-killer是一种自我保护机制,当系统分配不出内存时会触发这个机制,由操作系统在己有进程中挑选一个最适合的进程kill掉来释放内存。所以经常会碰到的情况就是每天某个点应用准挂,某天ssh登录不上,但ip是可以ping通的,这都有可能是进程被oom-killer干掉了。

     那为什么系统会发生oom-killer呢,这就还需要了解linux的内存overcommit机制,Linux分配内存时,也不是一次到位的真分配了指定大小的物理内存,而是先承诺你,实际用到的时候才去系统分配,这样做是出于优化系统考虑,因为不是所有的程序申请了内存就立刻使用的,当你使用的时候说不定系统已经回收了一些资源了,而如果刚好那个时候内存不够了,就会触发oom-killer。Linux下有3种Overcommit的策略(参考内核文档:vm/overcommit-accounting),可以在/proc/sys/vm/overcommit_memory配置。

   取0,1和2三个值,默认是0。
    0:启发式策略,比较严重的Overcommit将不能得逞,比如你突然申请了128TB的内存。而轻微的Overcommit将被允许。另外,root能Overcommit的值比普通用户要稍微多些。
    1:永远允许Overcommit,这种策略适合那些不能承受内存分配失败的应用,比如某些科学计算应用。
    2:永远禁止Overcommit,在这个情况下,系统所能分配的内存不会超过swap+RAM*系数(/proc/sys/vm/overcmmit_ratio,默认50%,你可以调整),如果这么多资源已经用光,那么后面任何尝试申请内存的行为都会返回错误,这通常意味着此时没法运行任何新程序。

 

    发生oom-killer时,哪个进程是最倒霉的,会被kill呢?说白了就是对系统性价比最高的那个,即付出少、收货高,具体就是比较/proc/<pid>/oom_score(系统会为每个进程都计算这个值,这个值是系统综合进程的内存消耗量、CPU时间(utime + stime)、存活时间(uptime - start time)和oom_adj计算出的,消耗内存越多分越高,存活时间越长分越低。总之,总的策略是:损失最少的工作,释放最大的内存同时不伤及无辜的用了很大内存的进程,并且杀掉的进程数尽量少。计算方法可以参考这里)中的值,值越大越容易被kill掉。

 

ps:查看系统日志文件路径,ubuntu是/var/log/kern.log,linux是/va/log/messages.log

原创粉丝点击