当我们要退出一个进程时只能按返回键,而该进程并没有真正的关闭,进程依然是存在于内存之中.这样设计的目的是为了下次能快速启动.当然,随着系统运行时间的增长,内存会越来越少,所以系统会定期执行一次检查,清理一些进程,释放掉内存.这就是Android的Low MemoryKiller机制
在kernel/drivers/staging/android/路径下的lowmemorykiller.c文件定义了lowmem_adj和lowmem_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进行动态调整。
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);
进程死后的善后
打印堆栈的方法:
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");
}