博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《深入理解Android2》读书笔记(八)
阅读量:6213 次
发布时间:2019-06-21

本文共 7918 字,大约阅读时间需要 26 分钟。

接上篇

AMS中的进程管理

AMS对进程的管理仅涉及两个方面

1.调节进程的调度优先级和调度策略

2.调节进程的oom值

调度优先级和调度策略

1.相对于在OS(操作系统)上运行的应用进程个数来说,CPU的资源非常有限

2.调度优先级是OS分配CPU资源给应用进程时(即调度应用进程运行)需要参考的一个指标。一般而言,优先级高的进程将更有机会得到CPU资源

3.除了优先级,还有一个需要考虑的重要因素是,每个进程所分配的时间片及它们的使用情况

Android应用进程分类:Forground类、Visible类、Service类、Background类及Empty类

Forground类

属于该类的进程包括下面几种情况

(1)含一个前端Activity(即onResume函数被调用过了,或者说当前正在显示的那个Activity)

(2)含一个Service,并且该Service和一个前端Activity绑定(例如Music应用包括一个前端界面和一个播放Service,当我们一边听歌一边操作Music界面时,该Service即和一个前端Activity绑定)

(3)含一个调用了startForground的Service,或者该进程的Service正在调用其生命周期的函数(onCreate、onStart或onDestroy)

(4)该进程中有BroadcastReceiver实例正在执行onReceive函数

Visible类

看属于Visible类的进程中没有处于前端的组件,但是用户仍然能看到它们,例如位于一个对话框后的Activity界面。该类进程包括两种

(1)该进程包含一个仅onPaus被调用的Activity(即它还在前台,只不过部分界面被遮住)

(2)包含一个Service,并且该Service和一个Visible(或Forground)的Activity绑定

Service类

该类进程包含一个Service。此Service通过startService启动,并且不属于前面两类进程。这种进程一般在后台默默干活。

Background类

该类进程包含当前不可见的Activity(即它们的onStop被调用过)。系统保存这些进程到一个LRU(最近最少使用)列表。当系统需要回收内存时,该列表中哪些最近最少使用的进程将被杀死

Empty类

这类进程不包含任何组件。为什么会出现这种不包括任何组件的进程呢?是因为,假设该进程进创建一个Activity,它完成工作后主动调用finish函数销毁(destory)自己,之后该进程就会成为Empty进程。系统保留Empty进程的原因是当又重新需要它们时(例如用户在别的进程中通过startActivity启动了它们),可以省去fork进程、创建Android运行环境等一系列漫长而艰苦的工作

应用进程Crash处理

private static class UncaughtHandler implements Thread.UncaughtExceptionHandler {    public void uncaughtException(Thread t, Throwable e) {        try {            // Don't re-enter -- avoid infinite loops if crash-reporting crashes.            if (mCrashing) return;            mCrashing = true;            if (mApplicationObject == null) {                Clog_e(TAG, "*** FATAL EXCEPTION IN SYSTEM PROCESS: " + t.getName(), e);            } else {                StringBuilder message = new StringBuilder();                message.append("FATAL EXCEPTION: ").append(t.getName()).append("\n");                final String processName = ActivityThread.currentProcessName();                if (processName != null) {                    message.append("Process: ").append(processName).append(", ");                }                message.append("PID: ").append(Process.myPid());                Clog_e(TAG, message.toString(), e);            }            // Bring up crash dialog, wait for it to be dismissed            ActivityManagerNative.getDefault().handleApplicationCrash(                    mApplicationObject, new ApplicationErrorReport.CrashInfo(e));        } catch (Throwable t2) {            try {                Clog_e(TAG, "Error reporting crash", t2);            } catch (Throwable t3) {                // Even Clog_e() fails!  Oh well.            }        } finally {            // Try everything to make sure this process goes away.            Process.killProcess(Process.myPid());            System.exit(10);        }    }}

AMS

public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {    ProcessRecord r = findAppProcess(app, "Crash");    final String processName = app == null ? "system_server"            : (r == null ? "unknown" : r.processName);    handleApplicationCrashInner("crash", r, processName, crashInfo);}
private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {    long timeMillis = System.currentTimeMillis();    String shortMsg = crashInfo.exceptionClassName;    String longMsg = crashInfo.exceptionMessage;    String stackTrace = crashInfo.stackTrace;    if (shortMsg != null && longMsg != null) {        longMsg = shortMsg + ": " + longMsg;    } else if (shortMsg != null) {        longMsg = shortMsg;    }    AppErrorResult result = new AppErrorResult();    synchronized (this) {        if (mController != null) {            try {                String name = r != null ? r.processName : null;                int pid = r != null ? r.pid : Binder.getCallingPid();                int uid = r != null ? r.info.uid : Binder.getCallingUid();                if (!mController.appCrashed(name, pid,                        shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {                    if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"))                            && "Native crash".equals(crashInfo.exceptionClassName)) {                        Slog.w(TAG, "Skip killing native crashed app " + name                                + "(" + pid + ") during testing");                    } else {                        Slog.w(TAG, "Force-killing crashed app " + name                                + " at watcher's request");                        if (r != null) {                            r.kill("crash", true);                        } else {                            // Huh.                            Process.killProcess(pid);                            killProcessGroup(uid, pid);                        }                    }                    return;                }            } catch (RemoteException e) {                mController = null;                Watchdog.getInstance().setActivityController(null);            }        }        final long origId = Binder.clearCallingIdentity();        // If this process is running instrumentation, finish it.        if (r != null && r.instrumentationClass != null) {            Slog.w(TAG, "Error in app " + r.processName                  + " running instrumentation " + r.instrumentationClass + ":");            if (shortMsg != null) Slog.w(TAG, "  " + shortMsg);            if (longMsg != null) Slog.w(TAG, "  " + longMsg);            Bundle info = new Bundle();            info.putString("shortMsg", shortMsg);            info.putString("longMsg", longMsg);            finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);            Binder.restoreCallingIdentity(origId);            return;        }        // Log crash in battery stats.        if (r != null) {            mBatteryStatsService.noteProcessCrash(r.processName, r.uid);        }        // If we can't identify the process or it's already exceeded its crash quota,        // quit right away without showing a crash dialog.        if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {            Binder.restoreCallingIdentity(origId);            return;        }        Message msg = Message.obtain();        msg.what = SHOW_ERROR_MSG;        HashMap data = new HashMap();        data.put("result", result);        data.put("app", r);        msg.obj = data;        mUiHandler.sendMessage(msg);        Binder.restoreCallingIdentity(origId);    }    int res = result.get();    Intent appErrorIntent = null;    synchronized (this) {        if (r != null && !r.isolated) {            // XXX Can't keep track of crash time for isolated processes,            // since they don't have a persistent identity.            mProcessCrashTimes.put(r.info.processName, r.uid,                    SystemClock.uptimeMillis());        }        if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {            appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);        }    }    if (appErrorIntent != null) {        try {            mContext.startActivityAsUser(appErrorIntent, new UserHandle(r.userId));        } catch (ActivityNotFoundException e) {            Slog.w(TAG, "bug report receiver dissappeared", e);        }    }}
private boolean makeAppCrashingLocked(ProcessRecord app,        String shortMsg, String longMsg, String stackTrace) {    app.crashing = true;    app.crashingReport = generateProcessError(app,            ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);    startAppProblemLocked(app);    app.stopFreezingAllLocked();    return handleAppCrashLocked(app, "force-crash" /*reason*/, shortMsg, longMsg, stackTrace);}

面试:什么情况需要把进程移到前台?

解析:

1)进程中的某个Activity正在与用户进行交互(Activity的onResume()方法被调用)

2)绑定到与当前用户正在交互的activity的service所在的进程

3)进程中的某个service正运行在前台,即这个service的startForeground()方法被调用

4)进程中的某个Service正在执行生命周期回调方法(比如:onCreate()、onStart()或者onDestory())

5)进程中的BroadcastReceiver正在执行onReceive()方法

转载地址:http://febja.baihongyu.com/

你可能感兴趣的文章
hdu 1671 Phone List(字典树)
查看>>
论数据库访问组件的选择--火地晋大作读后感
查看>>
php socket服务端和OC客户端(简单的测试)
查看>>
Dialog with HTML skin using CDHtmlDialog and SetWindowRgn
查看>>
看开源代码利器—用Graphviz + CodeViz生成C/C++函数调用图(call graph)
查看>>
回车替换Tab 并不会 提交表单 IE Chrome 通过
查看>>
算法:基于 RingBuffer 的 Deque 实现
查看>>
SharePoint 2013技巧分享系列 - Active Directory同步显示用户照片
查看>>
Xcode :Missing file warnings
查看>>
Four Ways to Create a Thread
查看>>
Unity 物理引擎动力学关节
查看>>
黄聪:360浏览器、chrome开发扩展插件教程(1)开发Chrome Extenstion其实很简单
查看>>
新年是否应该跳槽去外包公司呢?
查看>>
【重温经典算法之二】快速排序
查看>>
浏览器是如何展示网页的
查看>>
架构:Hexagonal Architecture Guidelines for Rails(转载)
查看>>
同源策略
查看>>
各种C#数组的定义和初始化
查看>>
Fragment之间的通信
查看>>
插入排序实例
查看>>