Android 系统启动流程,字节跳动Android金三银四解析

} catch (Throwable ex) {
Log.e(TAG, “System zygote died with exception”, ex);
zygoteServer.closeServerSocket();
throw ex;
}
}

ZygoteInit.main()native层传入初始化参数调用,这里不再赘述,这边主要沿Java的framework层来分析系统的调用,结合上图和代码注释可以看到,加载参数有start-system-server,即startSystemServer=true赋值,紧接着下面会调用ZygoteServer.registerServerSocket(),也就是这里和ZygoteServer的通信用到的是LocalSocket,我们知道跨进程调用最常见的调用方式就是LocalSocketaidl,在framework里也有很多这样通信的。接下来就开启了SystemServer,后面是一个runSelectLoop(),这里其实是一个死循环,当抛出异常终止则会调用zygoteServer.closeServerSocket()来关闭socket连接。我们继续跟进startSystemServer看具体是如何开启系统服务的。

2.startSystemServer

/**

  • Prepare the arguments and fork for the system server process.
    /
    private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)
    throws Zygote.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,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010”,
    “–capabilities=” + capabilities + “,” + capabilities,
    “–nice-name=system_server”,
    “–runtime-args”,
    “com.android.server.SystemServer”,
    };
    ZygoteConnection.Arguments parsedArgs = null;

int pid;

try {
//传入准备参数,注意上面参数最后的"com.android.server.SystemServer"
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}

/* For child process */

// pid = 0 说明创建子进程成功,SystemServer此时拥有独立进程,可以独立在自己的进程内操作了
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}

zygoteServer.closeServerSocket();
// 处理SystemServer进程
handleSystemServerProcess(parsedArgs);
}

return true;
}

这个方法不是很长,看注释可以知道,主要是用来准备SystemServer进程的参数和forkSystemServer进程。前面一堆参数不用看,注意我添加中文注释的地方,传入的参数有一个内容为"com.android.server.SystemServer",这是SystemServer类的全限定名,接下来调用Zygote.forkSystemSeerver(),最后当pid=0时,也就是说明子进程创建成功,如果这时候有两个Zygote进程则等待第二个Zygote进程连接,关闭掉第一个Zygote进程和ZygoteServersocket连接。最后调用handleSystemServerProcess()来处理SystemServer进程。这里的Zygote.forkSystemServer()实际上是调用了native层的forkSystemServer()来fork子进程。这里主要跟进handleSystemServerProcess()看看是如何完成新fork的SystemServer进程的剩余工作的。

3.handleSystemServerProcess

/**

  • Finish remaining work for the newly forked system server process.
    */
    private static void handleSystemServerProcess(
    ZygoteConnection.Arguments parsedArgs)
    throws Zygote.MethodAndArgsCaller {

    // 默认为null,走Zygote.init()流程

if (parsedArgs.invokeWith != null) {

} else {
ClassLoader cl = null;
if (systemServerClasspath != null) {
// 创建类加载器,并赋予当前线程
cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);
Thread.currentThread().setContextClassLoader(cl);
}

/*

  • Pass the remaining arguments to SystemServer.
    */
    ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
    }

/* should never reach here */
}

parsedArgs.invokeWith默认是为null的,也就是走else流程,可以看到先创建了一个类加载器并赋予了当前线程,然后进入了ZygoteInit.zygoteInit()

4.ZygoteInit.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:
    • [--] <start class name> <args>
    • @param targetSdkVersion target SDK version
    • @param argv arg strings
      */
      public static final void zygoteInit(int targetSdkVersion, String[] argv,
      ClassLoader classLoader) throws Zygote.MethodAndArgsCaller {
      if (RuntimeInit.DEBUG) {
      Slog.d(RuntimeInit.TAG, “RuntimeInit: Starting application from zygote”);
      }
    • Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, “ZygoteInit”);
      RuntimeInit.redirectLogStreams();

      RuntimeInit.commonInit();
      // Zygote初始化
      ZygoteInit.nativeZygoteInit();
      // 应用初始化
      RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
      }

      这个方法不是很长,主要工作是Zygote的初始化和Runtime的初始化。Zygote 的初始化调用了native方法,里面的大致工作是打开/dev/binder驱动设备,创建一个新的binder线程,调用talkWithDriver()不断地跟驱动交互。 进入RuntimeInit.applicationInit()查看具体应用初始化流程。

      5.RuntimeInit.applicationInit

      protected static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
      throws Zygote.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;
      }

      // The end of of the RuntimeInit event (see #zygoteInit).
      Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

      // Remaining arguments are passed to the start class’s static main
      invokeStaticMain(args.startClass, args.startArgs, classLoader);
      }

      这个方法也不是很长,前面的一些配置略过,主要看解析参数和invokeStaticMain(),顾名思义,这里的目的是通过反射调用静态的main方法,那么调用的是哪个类的main方法,我们看传入的参数是args.startClass,我们追溯参数的传递过程,发现之前提到的一系列args被封装进ZygoteConnection.Arguments类中,这一系列参数原本是

      String args[] = {
      “–setuid=1000”,
      “–setgid=1000”,
      “–setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010”,
      “–capabilities=” + capabilities + “,” + capabilities,
      “–nice-name=system_server”,
      “–runtime-args”,
      “com.android.server.SystemServer”,
      };

      可以看到,唯一的类的全限定名是com.android.server.SystemServer,追述args = new Arguments(argv)的源码也可以找到答案:

      Arguments(String args[]) throws IllegalArgumentException {
      parseArgs(args);
      }

      private void parseArgs(String args[])
      throws IllegalArgumentException {
      int curArg = 0;
      for (; curArg < args.length; curArg++) {
      String arg = args[curArg];

      if (arg.equals(“–”)) {
      curArg++;
      break;
      } else if (!arg.startsWith(“–”)) {
      break;
      }
      }

      if (curArg == args.length) {
      throw new IllegalArgumentException(“Missing classname argument to RuntimeInit!”);
      }

      // startClass 为args的最后一个参数
      startClass = args[curArg++];
      startArgs = new String[args.length - curArg];
      System.arraycopy(args, curArg, startArgs, 0, startArgs.length);
      }
      }

      6.RuntimeInit.invokeStaticMain

      private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
      throws Zygote.MethodAndArgsCaller {
      Class<?> cl;

      try {
      cl = Class.forName(className, true, classLoader);
      } 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);
      }

      /*

      自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

      深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

      因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
      img
      img
      img
      img

      由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
      如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
      img

      总结

      现在新技术层出不穷,如果每次出新的技术,我们都深入的研究的话,很容易分散精力。新的技术可能很久之后我们才会在工作中用得上,当学的新技术无法学以致用,很容易被我们遗忘,到最后真的需要使用的时候,又要从头来过(虽然上手会更快)。

      我觉得身为技术人,针对新技术应该是持拥抱态度的,入了这一行你就应该知道这是一个活到老学到老的行业,所以面对新技术,不要抵触,拥抱变化就好了。

      Flutter 明显是一种全新的技术,而对于这个新技术在发布之初,花一个月的时间学习它,成本确实过高。但是周末花一天时间体验一下它的开发流程,了解一下它的优缺点、能干什么或者不能干什么。这个时间,并不是我们不能接受的。

      如果有时间,其实通读一遍 Flutter 的文档,是最全面的一次对 Flutter 的了解过程。但是如果我们只有 8 小时的时间,我希望能关注一些最值得关注的点。

      Android学习PDF+架构视频+面试文档+源码笔记

      (跨平台开发(Flutter)、java基础与原理,自定义view、NDK、架构设计、性能优化、完整商业项目开发等)

      不是我们不能接受的。

      如果有时间,其实通读一遍 Flutter 的文档,是最全面的一次对 Flutter 的了解过程。但是如果我们只有 8 小时的时间,我希望能关注一些最值得关注的点。

      Android学习PDF+架构视频+面试文档+源码笔记

      (跨平台开发(Flutter)、java基础与原理,自定义view、NDK、架构设计、性能优化、完整商业项目开发等)

      [外链图片转存中…(img-JN7hnrPc-1710768375388)]

    • 22
      点赞
    • 20
      收藏
      觉得还不错? 一键收藏
    • 0
      评论
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值