前面已经讲到,从C/C++层进入了Java层,即调用了ZygoteInit.main()函数,那么接下来会发生什么事情呢?

源码参考Android4.1.1,涉及的文件有ZygoteInit.java,RuntimeInit.java(framework文件夹下)

ZygoteInit.main():

public static void main(String argv[]) {

try {

// Start profiling the zygote initialization.

SamplingProfilerIntegration.start();

//创建服务端的socket

registerZygoteSocket();

EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,

SystemClock.uptimeMillis());

// 最终调用preloadClasses();preloadResources();两个函数,

//加载class文件和res资源

preload();

EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,

SystemClock.uptimeMillis());

// Finish profiling the zygote initialization.

SamplingProfilerIntegration.writeZygoteSnapshot();

// Do an initial gc to clean up after startup

gc();

//这里的argv就是在C层产生的字符串数组,有两个元素

// If requested, start system server directly from Zygote

if (argv.length != 2) {

throw new RuntimeException(argv[0] + USAGE_STRING);

}

//显然,条件成立

if (argv[1].equals("start-system-server")) {

//这是要真刀真枪的开启SS进程了

startSystemServer();

} else if (!argv[1].equals("")) {

throw new RuntimeException(argv[0] + USAGE_STRING);

}

Log.i(TAG, "Accepting command socket connections");

if (ZYGOTE_FORK_MODE) {

runForkMode();

} else {

//这个函数其实也很重要,简而言之,让zygote休眠,但是随时能接受消息

//从loop字眼也可以看出循环的意思,后面的文章会在提到这个

runSelectLoopMode();

}

closeServerSocket();

} catch (MethodAndArgsCaller caller) {

caller.run();

} catch (RuntimeException ex) {

Log.e(TAG, "Zygote died with exception", ex);

closeServerSocket();

throw ex;

}

}

再看看startSystemServer()函数

private static boolean startSystemServer()

throws MethodAndArgsCaller, RuntimeException {

/* Hardcoded command line to start the system server */

String args[] = {//参数

"--setuid=1000",

"--setgid=1000",

"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003,3006,3007",

"--capabilities=130104352,130104352",

"--runtime-init",

"--nice-name=system_server",

"com.android.server.SystemServer",

};

ZygoteConnection.Arguments parsedArgs = null;

int pid;

try {

parsedArgs = new ZygoteConnection.Arguments(args);

ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);

ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

/* Request to fork the system server process */

pid = Zygote.forkSystemServer(//fork一个子进程

parsedArgs.uid, parsedArgs.gid,

parsedArgs.gids,

parsedArgs.debugFlags,

null,

parsedArgs.permittedCapabilities,

parsedArgs.effectiveCapabilities);

} catch (IllegalArgumentException ex) {

throw new RuntimeException(ex);

}

/* For child process */

if (pid == 0) {//子进程,即system_server进程

handleSystemServerProcess(parsedArgs);

}

return true;

}

果然看到了forkSystemServer这样的函数了,接下来在子进程中调用了handleSystemServerProcess()函数:

/**

* Finish remaining work for the newly forked system server process.

*/

private static void handleSystemServerProcess(

ZygoteConnection.Arguments parsedArgs)

throws ZygoteInit.MethodAndArgsCaller {

closeServerSocket();

// set umask to 0077 so new files and directories will default to owner-only permissions.

FileUtils.setUMask(FileUtils.S_IRWXG | FileUtils.S_IRWXO);

//niceName?

if (parsedArgs.niceName != null) {

Process.setArgV0(parsedArgs.niceName);

}

if (parsedArgs.invokeWith != null) {

WrapperInit.execApplication(parsedArgs.invokeWith,

parsedArgs.niceName, parsedArgs.targetSdkVersion,

null, parsedArgs.remainingArgs);

} else {

/*

* Pass the remaining arguments to SystemServer.

*/

//显然就是这个函数最重要了,

RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);

}

}

需要注意的是zygoteInit()函数是RuntimeInit类直接调用的,说明它是静态函数,在RuntimeInit.java文件中,zygoteInit()函数如下:

/**

* The main function called when started through the zygote process. This

* could be unified with main(), if the native code in nativeFinishInit()

* were rationalized with Zygote startup.

*

* Current recognized args:

*

*

[--]

*

*

* @param targetSdkVersion target SDK version

* @param argv arg strings

*/

public static final void zygoteInit(int targetSdkVersion, String[] argv)

throws ZygoteInit.MethodAndArgsCaller {

if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");

redirectLogStreams();

commonInit();

//本地zygoteInit函数,主要职责是C++层的初始化

nativeZygoteInit();

//另外的一些初始化工作

applicationInit(targetSdkVersion, argv);

}

本地的zygoteInit函数我们先放在一边,先看applicationInit函数:

private static void applicationInit(int targetSdkVersion, String[] argv)

throws ZygoteInit.MethodAndArgsCaller {

// If the application calls System.exit(), terminate the process

// immediately without running any shutdown hooks. It is not possible to

// shutdown an Android application gracefully. Among other things, the

// Android runtime shutdown hooks close the Binder driver, which can cause

// leftover running threads to crash before the process actually exits.

nativeSetExitWithoutCleanup(true);

// We want to be fairly aggressive about heap utilization, to avoid

// holding on to a lot of memory that isn't needed.

VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);

VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);

final Arguments args;

try {

//一些参数设定

args = new Arguments(argv);

} catch (IllegalArgumentException ex) {

Slog.e(TAG, ex.getMessage());

// let the process exit

return;

}

// Remaining arguments are passed to the start class's static main

//英文解释的其实已经比较明白了,

invokeStaticMain(args.startClass, args.startArgs);

}

再来看看invokeStaticMain函数,很明显,调用了JNI.

private static void invokeStaticMain(String className, String[] argv)

throws ZygoteInit.MethodAndArgsCaller {

Class> cl;

try {

//获取类对象

cl = Class.forName(className);

} catch (ClassNotFoundException ex) {

throw new RuntimeException(

"Missing class when invoking static main " + className,

ex);

}

Method m;

try {

//获取方法

m = cl.getMethod("main", new Class[] { String[].class });

} catch (NoSuchMethodException ex) {

throw new RuntimeException(

"Missing static main on " + className, ex);

} catch (SecurityException ex) {

throw new RuntimeException(

"Problem getting static main on " + className, ex);

}

int modifiers = m.getModifiers();

if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {

throw new RuntimeException(

"Main method is not public and static on " + className);

}

/*

* This throw gets caught in ZygoteInit.main(), which responds

* by invoking the exception's run() method. This arrangement

* clears up all the stack frames that were required in setting

* up the process.

*/

throw new ZygoteInit.MethodAndArgsCaller(m, argv);

##居然主动抛出异常?!!,what‘s the shit?

}

好吧,我在手心连写十个“忍”,继续还是心平气和的看代码,其实只要往上追溯,由于上层的方法都选择抛出该异常,最终追溯到了ZygoteInit.main()方法中,

在回顾main函数(部分):

try {

.........

.........

.........

if (argv[1].equals("start-system-server")) {

startSystemServer();

} else if (!argv[1].equals("")) {

throw new RuntimeException(argv[0] + USAGE_STRING);

}

Log.i(TAG, "Accepting command socket connections");

if (ZYGOTE_FORK_MODE) {

runForkMode();

} else {

runSelectLoopMode();

}

closeServerSocket();

} catch (MethodAndArgsCaller caller) {

##shit!!,在这里catch到了这个异常,看来是有意为之了

caller.run();

} catch (RuntimeException ex) {

Log.e(TAG, "Zygote died with exception", ex);

closeServerSocket();

throw ex;

}

好,caller对象是(MethodAndArgsCaller类型的,继续看caller.run()做了什么:

......

......

public void run() {

try {

##kidding me ??!!,在这里调用了SystemServer.main()方法?

mMethod.invoke(null, new Object[] { mArgs });

//有兴趣的同学可以研究一下mArgs里面都是些什么

} catch (IllegalAccessException ex) {

throw new RuntimeException(ex);

} catch (InvocationTargetException ex) {

Throwable cause = ex.getCause();

if (cause instanceof RuntimeException) {

throw (RuntimeException) cause;

} else if (cause instanceof Error) {

throw (Error) cause;

}

throw new RuntimeException(ex);

}

}

问题到这里可以说结束了,最终(fork的子进程)调用了SystemServer.main()函数,相当于创造了SystemS进程。

那么问题来了,为什么不在主动抛出异常的的地方直接调用main方法?

说实话,我不是很理解,但是看了邓平凡大大的《深入理解Android I》(是本好书,值得推荐),里面给出了一种解释那就是释放堆栈中被浪费的资源。

稍微解释一下,就是函数的调用是需要利用调用堆栈来实现的,每调用一个函数,原来的函数的资源会被压入栈,如果嵌套调用的函数多了的话,会占用系统资源。而关键在于SystemServer进程是不会死的(如果死了的话,系统也挂掉了),所以,也就意味着在这之前占用的那些资源不会被释放,so.......

多说一句,这种方式似乎达成了exec的函数调用的效果,上一篇文章提到,fork往往和exec一起用,可以造就两个不同的进程,但是实际上exec系统调用的工作原理是替换原来的进程的执行内容,只保留进程ID,可以说exec系统调用会擦除之前的进程积压的资源,这种抛异常的方式从某种程度上来讲实现了exec的效果。

android:process=.server,Android启动(三)----开启SystemServer进程相关推荐

  1. Android筑基——Activity的启动过程之同进程在一个Activity中启动另一个Activity(基于api21)

    目录 1. 前言 2. 正文 2.1 Activity类的startActivity()方法 2.2 Instrumentation类的execStartActivity()方法 2.3 Activi ...

  2. android android:process=,关于android:Android-appprocess的使用

    环境 win10 + android studio 先筹备一个HelloWorld.java类 public class HelloWorld { public static void main(St ...

  3. Android 系统(246)---SystemServer进程的启动流程

    Android进程系列第四篇---SystemServer进程的启动流程 一.内容预览 内容预览.png 二.概述 前面进程系列已经更新了三篇,本文(基于Android O源码),第三篇中System ...

  4. 从源码角度看Android系统SystemServer进程启动过程

    SystemServer进程是由Zygote进程fork生成,进程名为system_server,主要用于创建系统服务. 备注:本文将结合Android8.0的源码看SystemServer进程的启动 ...

  5. Android系统(245)---SystemServer进程的创建流程

    Android进程系列第三篇---SystemServer进程的创建流程 一.内容预览 SystemServer进程的启动.png 二.概述 前面进程系列已经更新了两篇,本文(基于Android O源 ...

  6. 源码详解Android 9.0(P) 系统启动流程之SystemServer

    源码详解Android 9.0(P) 系统启动流程目录: 源码详解Android 9.0(P)系统启动流程之init进程(第一阶段) 源码详解Android 9.0(P)系统启动流程之init进程(第 ...

  7. android取消自动调试模式吗,Android进入调试模式的三种技巧

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? Android开发过程中难免会遇到各种问题,通常我们会通过打印Log日志或者Debug模式来分析问题.这里介绍下Andr ...

  8. Android清单文件详解(三)----应用程序的根节点application

    <application>节点是AndroidManifest.xml文件中必须持有的一个节点,它包含在<manifest>节点下.通过<application>节 ...

  9. android 行为采集,Android AccessibilityService实现第三方APP行为捕获

    AccessibilityService实现行为捕获 语音:Kotlin 版本:1.2.41 最近接到一个很奇葩的需求:捕获系统语音通话聊天(包括微信.电话.QQ),把通话内容记录成音频文件上传到服务 ...

最新文章

  1. 第八课.特征工程与CTR预测
  2. 2019.03.18 连接my sql
  3. rest项目的基础返回类设计
  4. vue--为什么data属性必须是一个函数
  5. 编写一个函数实现从 1 到 n 共 n 个数的累加_leetcode306_go_累加数
  6. 关于tomcat出现闪退问题
  7. matlab中打不开保存好的模糊控制器,【求助大神】模糊控制器仿真,在Simulink运行时出现问题...
  8. 【296天】我爱刷题系列055(2017.11.28)
  9. 怎样获取linux命令帮助?
  10. Android之仿网易V3.5新特性
  11. 洛谷入门题P1046、P1047、P1427、P1428、P2141、P1567题解(Java语言描述)
  12. res.data.data_在Data.gov进行幕后推销
  13. Mac系统下安装MySQL详细步骤
  14. html 中的name,id ,value,class,list 作用与区别
  15. Spring Cloud Alibaba系列教程-03-搭建生产可用的Nacos集群
  16. 威纶触摸屏485轮询通讯_【威纶】触摸屏 界面制作软件 EBpro使用手册.pdf
  17. FPGA 38译码器
  18. 【python初级】 ubuntu18.04下卸载Anaconda3
  19. 电池SOC估计-EKF UKF
  20. 幼儿园体育游戏电子计算机教案,幼儿园体育游戏《学会跳绳》教案三篇

热门文章

  1. 解决LiteIDE 中的error process failed to start.
  2. 如何让“远程登录”更安全
  3. SpringBoot(十二)_springboot整合PageHelper
  4. python常用的数据预处理方法
  5. css过渡transition
  6. 如何隐藏android的屏幕上的Title Bar
  7. 腾讯财付通漏洞遭***利用 威胁QQ彩钻等付费用户
  8. Master/Slave知识
  9. ALV 层级分组显示报表
  10. 采购订单更改日期的妙用