android process die的原因分析介绍

1:低内存查杀LMK(low memory killer)

当我们要退出一个进程时只能按返回键,而该进程并没有真正的关闭,进程依然是存在于内存之中.这样设计的目的是为了下次能快速启动.当然,随着系统运行时间的增长,内存会越来越少,所以系统会定期执行一次检查,清理一些进程,释放掉内存.这就是Android的Low MemoryKiller机制

kernel/drivers/staging/android/路径下的lowmemorykiller.c文件定义了lowmem_adjlowmem_minfree两个数组,一个是adj 数组,描述process所对应的oom_adj,另外一个是minfree数组,描述process所对应的memory 的阈值

staticshortlowmem_adj[6]= {

    0,

    1,

    6,

    12,

};

staticint lowmem_adj_size= 4;

staticintlowmem_minfree[6] = {

    3 * 512,    /* 6MB*/

    2 * 1024,   /* 8MB*/

    4 * 1024,   /* 16MB*/

    16 * 1024/* 64MB*/

};

·        Low Memory Killer在用户空间中指定了一组内存临界值,当其中的某个值与进程描述中的oom_adj值在同一范围时,该进程将被Kill

·        


Android中的oom相关参数在init.rc中进行初始化配置,在系统运行时由ActivityManagerService进行动态调整。

C:\Windows\System32>adbshell cat /sys/module/lowmemorykiller/parameters/minfree

18432,23040,27648,32256,55296,80640                          

以上数字的单位是page. 1 page = 4 kb

C:\Windows\System32>adbshell cat /sys/module/lowmemorykiller/parameters/adj

0,100,200,300,900,906


2:am kill

am杀进程都是通过调用ProcessRecord.java中的kill函数。

void kill(String reason, boolean noisy)

这个函数执行本身就能够打印信息,打印堆栈信息可以使用fillInstackTrace()函数显示。

void kill(String reason, boolean noisy)---->Process.killProcessQuiet(pid);

           ---->ActivityManagerService.killProcessGroup(uid, pid);

3:crash/finsh

一个进程crash后,当系统有充足的内存情况下,还会被重新启动起来。

在ActivityManagerService.java函数handleApplicationCrashInner对app crash进行处理。

   void handleApplicationCrashInner(StringeventType, ProcessRecord r, String processName,

            ApplicationErrorReport.CrashInfocrashInfo) {

       EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),

               UserHandle.getUserId(Binder.getCallingUid()), processName,

                r == null ? -1 : r.info.flags,

                crashInfo.exceptionClassName,

                crashInfo.exceptionMessage,

                crashInfo.throwFileName,

                crashInfo.throwLineNumber);

 

        addErrorToDropBox(eventType, r,processName, null, null, null, null, null, crashInfo);

 

        mAppErrors.crashApplication(r,crashInfo);

    }

最后堆栈信息可以再AppErrors.java中的crashApplicationInner函数中进行打印出来。

crashApplicationInner ---> crashApplication---> handleAppCrashLocked---> removeProcessLocked--> kill(reason, true);

进程死后的善后
在应用进程fork后的attach步骤中,有类似如下的代码
public final void  attachApplication(IApplicationThread thread) {        
synchronized (this) {            
int callingPid = Binder.getCallingPid();           
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
 
private final  boolean attachApplicationLocked(IApplicationThread thread,
    ......          
try
 {
            AppDeathRecipient adr = new AppDeathRecipient(app, pid, thread);
            thread.asBinder().linkToDeath(adr, 0);
            app.deathRecipient = adr;
        } catch (RemoteException e) {
            app.resetPackageList(mProcessStats);
            startProcessLocked(app, "link fail", processName);
            return false;
        }
        ......
}
thread就是ApplicationThread类型的实例,这段代码向ApplicationThread注册了一个死亡通知,当app的进程被杀死后,AppDeathRecipient的binderDied函数将会被调用。


        
public void binderDied() {           
if(DEBUG_ALL) Slog.v(TAG, "Death received in " + this + " for thread " + mAppThread.asBinder());
            
synchronized(ActivityManagerService.this) {
                appDiedLocked(mApp, mPid, mAppThread, true);
            }
        }
appDiedLocked做的工作主要是清理。在cleanUpApplicationRecordLocked函数中还会检查App的android:persistent是否设置了,如果设置了会重启该应用。

打印堆栈的方法:

public void ThrowException() { 

       // 调试打印堆栈而不退出 

       Log.d(TAG, Log.getStackTraceString(new Throwable())); 

 

       // 创建异常打印堆栈 

       Exception e = new Exception("this is a log"); 

       e.printStackTrace(); 

 

       // 获取当前线程的堆栈 

       for (StackTraceElement i : Thread.currentThread().getStackTrace()){ 

           Log.i(TAG, i.toString()); 

       } 

 

       RuntimeException re = new RuntimeException(); 

       re.fillInStackTrace(); 

       Log.i(TAG, "stackTrace", re); 

 

       // 主动抛出异常调试 

       try { 

          Log.i(TAG,"--------------------------NullPointerException-----------1");              throw newNullPointerException(); 

        }catch (NullPointerException e1) { 

           // TODO: handle exception 

           Log.i(TAG,"--------------------------------NullPointerException"); 

           Log.e(TAG, Log.getStackTraceString(e1)); 

           // e1.printStackTrace(); 

       } 

Log.i(TAG,"--------------------------------NullPointerException-----------end");

   }  

猜你喜欢

转载自blog.csdn.net/fan380485838/article/details/80936626