当前位置:首页 > 嵌入式培训 > 嵌入式学习 > 讲师博文 > Android init进程之如何进入java世界

Android init进程之如何进入java世界 时间:2018-09-26      来源:未知

上一节我们了解了一下Android的init启动流程,我们知道在init进程启动的过程中,开启 了很多服务。我们也知道Android上层的应用程序是用Java语言编写的,Java语言编写的 程序需要放在Java虚拟机中运行,为了提高Android App应用程序的效率,google公司提 供了经过优化之后的Dalvik虚拟机来运行上层Java语言编写的程序。

好了,抛出两个问题:

1、Android系统是如何从C/C++世界进入Java世界的呢?

2、Android系统是如何运行上层的APP应用程序的呢?

一、zygote进程介绍

回顾上一节我们知道init进程在启动过程中启动了一个叫做zygote服务。在Android 中,zygote是整个系统创建新进程的核心装置。从字面上看,zygote是受精卵的意思,它 的主要工作就是进行细胞分裂。zygote进程内部会先启动Dalvik虚拟机,继而加载一些必 要的系统资源和系统类,后进入一种监听状态。在后续的运作中,当其他系统模块(比 如AMS)希望创建新进程时,只需要向zygote进程发出请求,zygote进程监听到请求后, 会相应地"分裂"出新的进程,于是这个新进程在出生之时,就先天具有了自己的Dalvik 虚拟机及系统资源。

zygote服务在init.zygote32.rc文件中描述如下:

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server

class main

socket zygote stream 660 root system

onrestart write /sys/android_power/request_state wake

onrestart write /sys/power/state on

onrestart restart media

onrestart restart netd

init进程在运行app_process时根据如下规则传递参数,app_process参数形式如下:

app_process [java-options] cmd-dir start-class-name [options]

(1)[java-options] : 传递给虚拟机的选项,必须以"-"开始

(2)cmd-dir : 所要运行的进程所在的目录

(3)start-class-name : 要在虚拟机中运行的类的名称。app_process会将制定的类加载到 虚拟机中,而后调用类的main()方法。

(4)[options] : 要传递给类的选项

根据参数规则,可以知道-Xzygote是指要传递给VM的选项。"-Xzygote"选项用来区分要 在虚拟机中运行的类是Zygote,还是在Zygote中运行其他Android应用程序,“--zygote”表示 加载com.android.internal.os.zygoteInit类。后一个参数"--start-system-server"作为选项传 递给生成的类,用于启动运行系统服务器。

好了,了解完这些以后,我们来看看zygote的详细实现。

二、zygote服务创建过程分析

通过前面的分析,我们知道zygote对应的应用程序是/system/bin/app_process,它对应的源 代码在framework\base\cmds\app_process\app_main.cpp文件中。

可以看到在运行app_process应用程序的时候,传递了"--zygote"参数,所以这里会调用到runtime.start("com.android.internal.os.ZygoteInit","args");这句话的含义是加载com.android.internal.os.ZygoteInit类运行。我们先来看 看runtime.start()函数的实现。

这段代码主要用途如下如下:

(1)jni_invocation.Init(NULL)初始化jni接口

(2)startVM(&mJavaVM,&env)启动Dalvik虚拟机

(3)startReg(env)注册jni函数接口,方便Java世界与C/C++世界沟通

(4)FindClass(slashClassName)通过根据类名解析出来的路径查找指定的类

(5)env->GetStaticMethodID()获取指定指定类的main函数接口

(6)env->CallStaticVoidMethod()调用指定的函数接口

跋山涉水,终于构造出了Java世界(AndroidRuntime---Dalvik虚拟机),接下来我们就开始在Java世界中加载第一个类:ZygoteInit运行。

三、ZygoteInit类运行过程分析

好了,至此我们从苦逼的C/C++世界进入了高富帅的Java世界,下面我们来看看 ZygoteInit类所做的事情,它对应的源代码 在frameworks\base\core\java\com\android\internal\os\ZygoteInit.java中。

这段代码的主要用途如下:

(1)registerZygoteSocket(socketName),这个函数用来绑定套接字,以便接收新Android应用 程序的运行请求。Zygote使用UDS(Unix Domain Socket),为了从接 收ActivityManagerService(AMS)发来的新Android应用程序的运行请求。

(2)preload()函数实现如下:

static void preload() {

Log.d(TAG, "begin preload"); preloadClasses(); //加载

preloadResources(); preloadOpenGL(); preloadSharedLibraries();

// Ask the WebViewFactory to do any initialization that must run in the zygote process,

// for memory sharing purposes. WebViewFactory.prepareWebViewInZygote(); Log.d(TAG, "end preload");

}

可以看到zygote进程在运行的过程中加载了应用程序框架中的类、平台资源(图像、 XML信息、字符串等)预先加载到内存中。新进程直接使用这些类与资源,而不需要重 新加载他们,这大大加快了程序的执行速度。

------------------------------------------------------------------------------------------------------------------------

加载应用程序Framework中包含的资源 在Android应用程序Framework中使用的字符串、颜色、图像文件、音频文件等都被 称为资源。应用程序不能直接访问这些资源,需要通过Android开发工具自动生成的 R类来访问。通过R类可访问的资源组成信息记录在XML中。Android资源大致可以 分为两大类,如下:

<1>Drawable 这类资源是指画面、照片、图标等可在画面中绘画的资源。preloadResource会加载 按钮图片、按钮组等基本主题图像。Android应用程序Framework中包含CheckBox、 Button、Editbox、Call等图像文件。

<2>XML管理的资源

XML管理的资源有保存字符串的strings.xml、保存字符串数组的arrays.xml,以及保 存颜色值得colors.xml等。此外,动画、布局等资源也是由XML文件管理的。

------------------------------------------------------------------------------------------------------------------------

(3)startSystemServer(abiList,socketName)

创建了一个子进程,然后在子进程中加载"com.android.server.SystemServer"类运行。下面 我们接着看看,它是如何运行SystemServer类运行的。

关闭了从父进程那边继承过来的套接字文件描述符,然手调用了RuntimInit.zygoteInit()方法。这个方法在frameworks\base\core\java\com\android\internal\os\RuntimeInit.java文件中定义,我们来看看它的具体实现

通过Class.forName加载SystemServer类,然后通过cl.getMethod()方法获取SystemServer类 的main方法。 在这里我们并没有看到直接调用这个"main"方法,而是抛出了一个一个异常。通过注释 我们可以知道,这个异常

终会被ZygtoeInit.main()函数捕获。

我们来看看caller.run()方法的实现。

很简单啦,调用指定的方法。我们这里就是SystemServer类的main方法。嗯,至此SystemServer这个进程就创建 成功了。创建子进程成功后,我们的父进程zygote从startSystemServer()函数返回后,会 调用runSelectLoop()方法。

从注释中我们就可以知道,zygote进程终一直在runSelectLoop函数工作。这个函数 终就会调用到C/C++层 的select函数,探测socket文件描述附是否就绪。如果有,则说明ActivityManagerService向它发出了"启动新应用进程" 的命令,zygote进程收到命令后,就会fork一个子进程,然后在子进程中抛出一个 MethodAndArgsCaller异常。 终会被ZygoteInit.main()函数捕获,然后调用call.run()方法,终调用需要运行类 的main方法,这样应用程序就跑起来啦。

好了,下面我们画一幅图总结一下zygote进程做的的事情:

四、SystemServer服务分析

通过前面的分析我们知道SystemServer是zygote进程孵化出来的第一个进程,它在 Android的运行环境中扮演了"神经中枢"的作用,APK应用中能够直接交互的大部分系统 服务都在该进程中运行,常见的比如WindowManagerServer(WMS)、 ActivityManagerSystemService(AMS)、PackageManagerServer(PMS)等,这些系统服务都是 以一个线程的方式存在于SystemServer进程中。所以SystemServer关系了整个Java世界 的生死存亡,如果SystemServer进程异常退出,zygote进程知道后就会"自杀",接着init 进程重新启动zygote进程,从而再次开启Java世界。

下面我们简单分析一下SystemServer的运行过程:

frameworks\base\services\java\com\android\server\SystemServer.java

从上述代码中我们可以看到SystemServer中启动了Java世界中所需要的服务,它分为核心 平台服务与硬件服务

(1)核心平台服务(Core Platform Service) 一般而言,核心平台服务不会直接与Android应用程序进行交互,但它们是Android Framework运行所必须的服务,其包含的主要服务如下表所示:

(2)硬件服务(Hardware Service)

该服务提供了一系列的API,用户控制底层硬件, 主要服务包含如下

五、监听zygote socket分析

ZygoteInit的main()函数在调用完startSystemServer()之后,就会调用runSelectLoop()函数, 它的代码如下:

frameworks\base\core\java\com\android\internal\os\ZygoteInit.java

这段代码完成的功能如下: (1)通过selectReadable()函数探测是否有连接请求

(2)如果有则调用acceptCommandPeer()函数,提取添加请求,并且把已连接的文件描述符 添加到文件描述符集合中

(3)如果有zygote socket中有数据到达,则调用peers.get(index).runOnce()函数。

runOnce()函数的实现代码如下: frameworks\base\core\java\com\android\internal\os\ZygoteConnection.java:

这段代码的功能如下: (1)调用Zygote.forkAndSpecialize()函数创建子进程 (2)调用handleChildProc()函数

可以看到这个函数终调用了ZygoteInit.invokeStaticMain()函数,这个函数间接抛出特殊 的MethodAndArgsCaller异常,只不过此时抛出的异常携带的类名为ActivityThread。

注意:ActivityThread类在运行的时候,也标示着我们APK应用程序的运行,它就是 APK应用程序的入口哦!等等,Android APP应用程序的入口不是onCreate()方法吗?呵呵!真正的入口是ActivityThread类, 这个类在运行的时候会间接调用到相应

类的onCreate()方法。

上一篇:如何实现Arm处理器ICache的测试

下一篇:Android.mk分析

热点文章推荐
华清学员就业榜单
高薪学员经验分享
热点新闻推荐
前台专线:010-82525158 企业培训洽谈专线:010-82525379 院校合作洽谈专线:010-82525379 Copyright © 2004-2022 北京华清远见科技集团有限公司 版权所有 ,京ICP备16055225号-5京公海网安备11010802025203号

回到顶部