美文网首页
Zygote冷启动流程

Zygote冷启动流程

作者: 馒Care | 来源:发表于2021-08-23 10:32 被阅读0次

http://liuwangshu.cn/framework/applicationprocess/1.html

SystemServer(SystemServer组件是由Zygote进程负责启动的,启动的时候就会调用它的main函数,这个函数主要调用了JNI方法init1来做一些系统初始化的工作。init1这个函数是一个JNI方法,实现在 frameworks/base/services/jni/com_android_server_SystemServer.cpp文件中:

通过startBootstrapServices,启动一堆服务,例如ActivityManagerService

ActivityManagerService会通过调用startProcessLocked函数来向Zygote进程发送请求,如下所示。

sdk版本28 代码4379行

//这里是关键,ActivityThread是后续整个启动的入口
// Start the process.  It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
final String entryPoint = "android.app.ActivityThread";
return startProcessLocked(hostingType, hostingNameStr, entryPoint, app, uid, gids,
                    runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith,
                    startTime);
调用到
 final ProcessStartResult startResult = startProcess(app.hostingType, entryPoint,
                            app, app.startUid, gids, runtimeFlags, mountExternal, app.seInfo,
                            requiredAbi, instructionSet, invokeWith, app.startTime);
再调用到
 Process.ProcessStartResult startResult = Process.start(entryPoint,
                  app.processName, uid, uid, gids, debugFlags, mountExternal,
                  app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
                  app.info.dataDir, entryPointArgs);
Process
public static final ProcessStartResult start(final String processClass,
                                  final String niceName,
                                  int uid, int gid, int[] gids,
                                  int runtimeFlags, int mountExternal,
                                  int targetSdkVersion,
                                  String seInfo,
                                  String abi,
                                  String instructionSet,
                                  String appDataDir,
                                  String invokeWith,
                                  String[] zygoteArgs) {
        return zygoteProcess.start(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
    }

Process.start调用startViaZygote

//创建了字符串列表argsForZygote ,并将启动应用进程的启动参数保存在argsForZygote中
ArrayList<String> argsForZygote = new ArrayList<>();

代码437行
 synchronized(mLock) {
            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
 }

zygoteSendArgsAndGetResult
zygoteSendArgsAndGetResult函数主要做的就是将传入的应用进程的启动参数argsForZygote,写入到ZygoteState中

private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
primaryZygoteState =
        ZygoteState.connect(mZygoteSocketAddress, mUsapPoolSocketAddress);
public ZygoteProcess() {
    mZygoteSocketAddress =
            new LocalSocketAddress(Zygote.PRIMARY_SOCKET_NAME,
                                   LocalSocketAddress.Namespace.RESERVED);
}
省略很多代码
}
com.android.internal.os.Zygote

Zygote.PRIMARY_SOCKET_NAME 
public static final String PRIMARY_SOCKET_NAME = "zygote";
Zygote.usapMain
ZygoteInit.zygoteInit
ZygoteInit.main
start-system-server 启动SystemServer--forkSystemServer
--enable-lazy-preload
caller = zygoteServer.runSelectLoop(abiList);//等待客户端请求
if (pollIndex == 0) {
    // Zygote server socket

    ZygoteConnection newPeer = acceptCommandPeer(abiList);
    peers.add(newPeer);
    socketFDs.add(newPeer.getFileDescriptor());

} else if (pollIndex < usapPoolEventFDIndex) {
    // Session socket accepted from the Zygote server socket

    try {
        ZygoteConnection connection = peers.get(pollIndex);
final Runnable command = connection.processOneCommand(this);

}
ZygoteConnection.processOneCommand
//获取应用程序进程的启动参数
args = Zygote.readArgumentList(mSocketReader);
//创建应用程序进程
Zygote.forkAndSpecialize

forkAndSpecialize函数主要是通过fork当前进程来创建一个子进程的,如果pid等于0,则说明是在新创建的子进程中执行的,就会调用handleChildProc函数来启动这个子进程也就是应用程序进程
handleChildProc

if (!isZygote) {
    return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
            parsedArgs.mDisabledCompatChanges,
            parsedArgs.mRemainingArgs, null /* classLoader */);
} else {
    return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion,
            parsedArgs.mRemainingArgs, null /* classLoader */);
}

ZygoteInit.zygoteInit—>RuntimeInit.applicationInit—>findStaticMain->invoke<android.app.ActivityThread>—>main函数

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);
}

链接:https://www.jianshu.com/p/f7a30554fe55
六,App启动、Application生命周期
app的两种启动方式

1,冷启动
系统会重新创建一个新的进程分配给它,所以会先创建和初始化Application类,再创建和初始化MainActivity类(包括一系列的测量、布局、绘制),最后显示在界面上

2,热启动
进程在后台运行,所以热启动就不会走Application这步了,而是直接走MainActivity(包括一系列的测量、布局、绘制),所以热启动的过程只需要创建和初始化一个MainActivity就行了,而不必创建和初始化Application,因为一个应用从新进程的创建到进程的销毁,Application只会初始化一次。

App启动流程
用户点击app后会通知 ActivityManagerService 启动应用的入口 Activity, ActivityManagerService 发现这个应用还未启动,则会通知 Zygote 进程孵化出应用进程,然后在这个应用进程里执行 ActivityThread 的 main 方法。应用进程接下来通知 ActivityManagerService 应用进程已启动,ActivityManagerService 保存应用进程的一个代理对象,这样 ActivityManagerService 可以通过这个代理对象控制应用进程,然后 ActivityManagerService 通知应用进程创建入口 Activity 的实例,并执行它的生命周期函数。

上面的启动流程是 Android 提供的机制,我们只能在创建入口 Activity 的实例这里做文章,正常Main Activity 的启动流程:

-> Application 构造函数
-> Application.attachBaseContext()
-> Application.onCreate()
-> Activity 构造函数
-> Activity.setTheme()
-> Activity.onCreate()
-> Activity.onStart
-> Activity.onResume
-> Activity.onAttachedToWindow
-> Activity.onWindowFocusChanged
统计app启动时长的两种方式

1,本地通过adb命令行
adb shell am start -w packagename/activity 输入adb shell am start -W

com.qcl/com.qcl.MainActivity得到下面结果
Activity: com.qcl/.MainActivity
ThisTime: 83
TotalTime: 83
WaitTime: 94
TotalTime是我们真正的启动时间
2,通过收集log(可以用来获取线上启动时间)
开始时间:
冷启动在Application的attachBaseContext
热启动在入口activity的onRestart中
结束时间:在入口activity的onWindowFocusChanged

app的启动优化:
基于上面的启动流程我们尽量做到如下几点

1.Application的创建过程中尽量少的进行耗时操作
2.如果用到SharePreference,尽量在异步线程中操作
3.减少布局的层次,并且生命周期回调的方法中尽量减少耗时的操作
app启动遇见黑屏或者白屏问题
1,产生原因
其实显示黑屏或者白屏实属正常,这是因为还没加载到布局文件,就已经显示了window窗口背景,黑屏白屏就是window窗口背景
2,解决办法
通过设置设置Style
(1)设置背景图Theme
通过设置一张背景图。 当程序启动时,首先显示这张背景图,避免出现黑屏
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:screenOrientation">portrait</item>
<item name="android:windowBackground">>@mipmap/splash</item>

<item name="android:windowIsTranslucent">true</item> 
<item name="android:windowNoTitle">true</item> 

</style>
设置透明Theme
通过把样式设置为透明,程序启动后不会黑屏而是整个透明了,等到界面初始化完才一次性显示出来

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:screenOrientation">portrait</item>
</style>
两者对比:
Theme1 程序启动快,界面先显示背景图,然后再刷新其他界面控件。给人刷新不同步感觉。
Theme2 给人程序启动慢感觉,界面一次性刷出来,刷新同步
Zygote参考

相关文章

  • Zygote冷启动流程

    http://liuwangshu.cn/framework/applicationprocess/1.html[...

  • Zygote冷启动 启动时间收集(一)

    冷启动 启动时间收集 上一篇说道Zygote启动流程,本篇描述冷启动时间收集 首先我们知道冷启动会先初始化Appl...

  • zygote的启动和作用

    zygote的作用(what) zygote的启动流程(how) zygote的工作原理(why) zygote的...

  • zygote android 应用启动之路

    android, zygote, systemservice启动流程 创建应用 1. 创建zygote socke...

  • Android Framework学习之zygote

    1.Zygote是什么? 2.Zygote的启动流程? 3.Zygote的工作原理? 虽然做android很...

  • zygote

    本文主要介绍zygote 流程 1 , 解析zygote 脚本,并运行mainandroid/system/cor...

  • zygote的理解

    谈一谈对Zygote的理解? Zygote的作用是什么? 启动三段式 Zygote的启动流程 Zygote进程是怎...

  • 性能优化 -- 启动优化

    启动优化 app启动分为:冷启动;热启动,温启动三种冷启动: 耗时最多流程:冷启动经过的流程点击app --> ...

  • Android 应用启动流程 | Activity 启动流程

    Android 系统启动流程启动 init 进程 , init 进程会启动 Zygote 进程Zygote 进程会...

  • 启动优化1

    目录 一、冷启动定义 二、 冷启动和热启动 三、冷启动、热启动的区别 四、冷启动时间的计算 五、冷启动流程 六、冷...

网友评论

      本文标题:Zygote冷启动流程

      本文链接:https://www.haomeiwen.com/subject/argkiltx.html