上一篇文章"Zygote-1.启动引导"中讲解了app_process可执行程序最后会调用如下2个类的main方法:
- com.android.internal.os.ZygoteInit:进入Zygote Java世界
- com.android.internal.os.RuntimeInit:启动指定的className
本篇文章从ZygoteInit.main进一步分析Zygote的启动流程,main的主要工作:
- 调用preload()来预加载类和资源;
- 调用ZygoteServer()创建两个Server端的Socket /dev/socket/zygote 和 /dev/socket/zygote_secondary,Socket用来等待ActivityManagerService来请求Zygote来创建新的应用 程序进程;
- 调用forkSystemServer 来启动SystemServer进程,这样系统的关键服务也会由SystemServer进程启动起来;
- 最后调用runSelectLoop函数来等待客户端请求;
//frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
@UnsupportedAppUsage
public static void main(String argv[]) {
//创建ZygoteServer
ZygoteServer zygoteServer = null;
// 调用native函数,确保当前没有其它线程在运行
// Mark zygote start. This ensures that thread creation will throw
// an error.
ZygoteHooks.startZygoteNoThreadCreation();
//设置pid为0,Zygote进入自己的进程组
// Zygote goes into its own process group.
try {
Os.setpgid(0, 0);
} catch (ErrnoException ex) {
throw new RuntimeException("Failed to setpgid(0,0)", ex);
}
Runnable caller;
try {
// Report Zygote start time to tron unless it is a runtime restart
if (!"1".equals(SystemProperties.get("sys.boot_completed"))) {
MetricsLogger.histogram(null, "boot_zygote_init",
(int) SystemClock.elapsedRealtime());
}
//得到systrace的监控TAG
String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";
TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag,
Trace.TRACE_TAG_DALVIK);
//通过systradce来追踪 函数ZygoteInit, 可以通过systrace工具来进行分析
//traceBegin 和 traceEnd 要成对出现,而且需要使用同一个tag
bootTimingsTraceLog.traceBegin("ZygoteInit");
//开启DDMS(Dalvik Debug Monitor Service)功能
//注册所有已知的Java VM的处理块的监听器。线程监听、内存监听、native 堆内存监听、debug模式监听等等
RuntimeInit.enableDdms();
}
....
}
最前面的部分代码主要是做了些前置准备工作。
boolean startSystemServer = false;
String zygoteSocketName = "zygote";
String abiList = null;
boolean enableLazyPreload = false;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if ("--enable-lazy-preload".equals(argv[i])) {
enableLazyPreload = true;
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
这部分代码将main传递过来的参数解析为对应的变量,第一次启动时参数中没有"--enable-lazy-preload",因此enableLazyPreload为false。
预加载资源
if (!enableLazyPreload) {
//traceBegin对preload方法调用统计分析
bootTimingsTraceLog.traceBegin("ZygotePreload");
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
// 预加载资源
preload(bootTimingsTraceLog);
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
bootTimingsTraceLog.traceEnd(); // ZygotePreload
} else {
Zygote.resetNicePriority();
}
当第一次启动时会先执行预加载,那什么是预加载?
预加载是指在zygote进程启动的时候就加载,这样系统只在zygote执行一次加载操作,所有APP用到该资源不需要再重新加载,减少资源加载时间,加快了应用启动速度,一般情况下,系统中App共享的资源会被列为预加载资源。
zygote fork子进程时,根据fork的copy-on-write机制可知,有些类如果不做改变,甚至都不用复制,子进程可以和父进程共享这部分数据,从而省去不少内存的占用。
预加载的原理?
zygote进程启动后将资源读取出来,保存到Resources一个全局静态变量中,下次读取系统资源的时候优先从静态变量中查找。
static void preload(TimingsTraceLog bootTimingsTraceLog) {
Log.d(TAG, "begin preload");
bootTimingsTraceLog.traceBegin("BeginPreload");
beginPreload();
bootTimingsTraceLog.traceEnd(); // BeginPreload
bootTimingsTraceLog.traceBegin("PreloadClasses");
//加载指定的类到内存并且初始化,使用的Class.forName(class, true, null);方式
preloadClasses();
bootTimingsTraceLog.traceEnd(); // PreloadClasses
bootTimingsTraceLog.traceBegin("CacheNonBootClasspathClassLoaders");
cacheNonBootClasspathClassLoaders();
bootTimingsTraceLog.traceEnd(); // CacheNonBootClasspathClassLoaders
bootTimingsTraceLog.traceBegin("PreloadResources");
//加载图片、颜色等资源文件,部分定义在 /frameworks/base/core/res/res/values/arrays.xml中
preloadResources();
bootTimingsTraceLog.traceEnd(); // PreloadResources
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadAppProcessHALs");
nativePreloadAppProcessHALs();
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadGraphicsDriver");
maybePreloadGraphicsDriver();
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
// 加载 android、compiler_rt、jnigraphics等library
preloadSharedLibraries();
//加载Text资源,字体等
preloadTextResources();
// Ask the WebViewFactory to do any initialization that must run in the zygote process,
// for memory sharing purposes.
// 为了内存共享,WebViewFactory进行任何初始化都要在Zygote进程中
WebViewFactory.prepareWebViewInZygote();
endPreload();
warmUpJcaProviders();
Log.d(TAG, "end preload");
sPreloadComplete = true;
}
- preloadClassess 将framework.jar里的preloaded-classes 定义的所有class load到内存 里,preloaded-classes编译Android源码后可以在framework/base下找到;
- preloadResources 将系统的Resource(不是在用户apk里定义的resource)load到内存。资源preload到Zygoted的进程地址空间, 所有fork的子进程将共享这份空间而无需重新load, 这大大减少了应用程序的启动时间,但反过来增加了系统的启动时间;
通过对preload 类和资源数目进行调整可以加快系统启动,Preload也是Android启动最耗时的部分之一。
// Do an initial gc to clean up after startup
bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
gcAndFinalize();
bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC
资源预加载完成后,就立刻执行可一次gc操作,因为后续将要执行fork创建SystemServer进程,而SystemServer进程中会创建Android系统绝大多数服务(AMS、WMS、PMS等),gc操作将垃圾内存尽可能早的释放,这样将来被复制出来的子进程才能暂用更少的内容。
创建socket
zygoteServer = new ZygoteServer(isPrimaryZygote);
ZygoteServer(boolean isPrimaryZygote) {
mUsapPoolEventFD = Zygote.getUsapPoolEventFD();
if (isPrimaryZygote) {
mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
mUsapPoolSocket =
Zygote.createManagedSocketFromInitSocket(
Zygote.USAP_POOL_PRIMARY_SOCKET_NAME);
} else {
mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.SECONDARY_SOCKET_NAME);
mUsapPoolSocket =
Zygote.createManagedSocketFromInitSocket(
Zygote.USAP_POOL_SECONDARY_SOCKET_NAME);
}
fetchUsapPoolPolicyProps();
mUsapPoolSupported = true;
}
ZygoteServer 构造函数初始化时,根据rc配置文件,利用LocalServerSocket 创建了4个本地服务端的socket,用来建立连接,分别是:zygote、usap_pool_primary、zygote_secondary、 usap_pool_secondary。
init.zygote64.rc配置文件创建 2 个socket:
//system/core/rootdir/init.zygote64.rc
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
class main
priority -20
user root
group root readproc reserved_disk
socket zygote stream 660 root system
socket usap_pool_primary stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
writepid /dev/cpuset/foreground/tasks
init.zygote64_32.rc配置文件创建 4 个socket:
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
class main
priority -20
user root
group root readproc reserved_disk
socket zygote stream 660 root system
socket usap_pool_primary stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
writepid /dev/cpuset/foreground/tasks
service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary --enable-lazy-preload
class main
priority -20
user root
group root readproc reserved_disk
socket zygote_secondary stream 660 root system
socket usap_pool_secondary stream 660 root system
onrestart restart zygote
writepid /dev/cpuset/foreground/tasks
启动SystemServer进程
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
if (r != null) {
r.run();
return;
}
forkSystemServer有 2 个主要作用:
- 调用fork创建出SystemServer子进程
- 主进程forkSystemServer返回空;子进程返回MethodAndArgsCaller对象,MethodAndArgsCaller继承Runnable,MethodAndArgsCaller.run方法中会执行com.android.server.SystemServer.main方法
因此,当调用r.run方法时SystemServer进程就开始启动了。
private static Runnable forkSystemServer(String abiList, String socketName,
ZygoteServer zygoteServer) {
....
/* 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,"
+ "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
"com.android.server.SystemServer",
};
ZygoteArguments parsedArgs = null;
int pid;
try {
//将上面准备的参数,按照ZygoteArguments的风格进行封装
parsedArgs = new ZygoteArguments(args);
...
/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.mUid, parsedArgs.mGid,
parsedArgs.mGids,
parsedArgs.mRuntimeFlags,
null,
parsedArgs.mPermittedCapabilities,
parsedArgs.mEffectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {
//子进程中关闭Zygote服务端socket,因为SystemServer进程中不需要
zygoteServer.closeServerSocket();
return handleSystemServerProcess(parsedArgs);
}
return null;
}
args参数中关注 2 个重要数据:
- --nice-name:指定进程名为system_server;
- com.android.server.SystemServer:指定运行的目标类;
然后调用Zygote.forkSystemServer内部调用nativeForkSystemServer,它是native方法,其对应的JNI方法如下:
//frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
static jint com_android_internal_os_Zygote_nativeForkSystemServer(
JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
jint runtime_flags, jobjectArray rlimits, jlong permitted_capabilities,
jlong effective_capabilities) {
std::vector<int> fds_to_close(MakeUsapPipeReadFDVector()),
fds_to_ignore(fds_to_close);
fds_to_close.push_back(gUsapPoolSocketFD);
if (gUsapPoolEventFD != -1) {
fds_to_close.push_back(gUsapPoolEventFD);
fds_to_ignore.push_back(gUsapPoolEventFD);
}
// ForkCommon 对 fork 进程了包装,针对 Android 平台各个进程的共性最同意的初始化操作
pid_t pid = ForkCommon(env, true,
fds_to_close,
fds_to_ignore);
if (pid == 0) {
SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
permitted_capabilities, effective_capabilities,
MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true,
false, nullptr, nullptr);
} else if (pid > 0) {
// The zygote process checks whether the child process has died or not.
ALOGI("System server process %d has been created", pid);
gSystemServerPid = pid;
// There is a slight window that the system server process has crashed
// but it went unnoticed because we haven't published its pid yet. So
// we recheck here just to make sure that all is well.
int status;
if (waitpid(pid, &status, WNOHANG) == pid) {
ALOGE("System server process %d has died. Restarting Zygote!", pid);
RuntimeAbort(env, __LINE__, "System server process has died. Restarting Zygote!");
}
if (UsePerAppMemcg()) {
// Assign system_server to the correct memory cgroup.
// Not all devices mount memcg so check if it is mounted first
// to avoid unnecessarily printing errors and denials in the logs.
if (!SetTaskProfiles(pid, std::vector<std::string>{"SystemMemoryProcess"})) {
ALOGE("couldn't add process %d into system memcg group", pid);
}
}
}
return pid;
}
ForkCommon对fork进程了包装,针对Android平台各个进程的共性做了统一的初始化操作。从这里可以看出 Zygote.forkSystemServer 实际是对 Native 层的 fork 调用的包装,用于启动一个 SystemServer 进程。
再回到 private static Runnable forkSystemServer(String abiList, String socketName, ZygoteServer zygoteServer) 函数中,SystemServer 进程返回(pid=0 表示子进程返回)后就会调用handleSystemServerProcess
private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {
...
if (parsedArgs.mInvokeWith != null) {
...
} else {
//创建ClassLoader
createSystemServerClassLoader();
ClassLoader cl = sCachedSystemServerClassLoader;
if (cl != null) {
Thread.currentThread().setContextClassLoader(cl);
}
/*
* Pass the remaining arguments to SystemServer.
*/
return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mRemainingArgs, cl);
}
/* should never reach here */
}
这里创建并设置ClassLoader,然后调用ZygoteInit.zygoteInit
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) {
if (RuntimeInit.DEBUG) {
Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
RuntimeInit.redirectLogStreams();
RuntimeInit.commonInit();
ZygoteInit.nativeZygoteInit();
return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
commonInit用于执行一些通用配置的初始化:
- 设置 KillApplicationHandler 为默认的 UncaughtExceptionHandler;
- 设置时区;
- 设置 http.agent 属性,用于 HttpURLConnection;
- 重置 Android 的 Log 系统;
- 通过 NetworkManagementSocketTagger 设置 socket 的 tag,用于流量统计;
nativeZygoteInit做初始化工作,它是一个native方法
//frameworks/base/core/jni/AndroidRuntime.cpp
static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->onZygoteInit();
}
gCurRuntime就是前面创建的AppRuntime实例,onZygoteInit在AppRuntime进行了实现。这部分代码在 Binder 中都介绍过了,主要用于初始化 Binder 的使用环境,这样应用进程就可以使用Binder了。
virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();
}
最后调用RuntimeInit.applicationInit
protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) {
// 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 = new Arguments(argv);
// 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
return findStaticMain(args.startClass, args.startArgs, classLoader);
}
- 设置虚拟机的 HeapUtilization 为 0.75f;
- 设置当前的 SDKVersion;
- 调用 findStaticMain函数来查找com.android.server.SystemServer类main方法,然后将main方法的Method对象和参数并包装成MethodAndArgsCaller(它继承Runnable);
protected static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
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);
}
return new MethodAndArgsCaller(m, argv);
}
返回MethodAndArgsCaller后,再调用r.run方法,这样就调用了com.android.server.SystemServer.main()开始进入SystemServer进程的初始化。
static class MethodAndArgsCaller implements Runnable {
/** method to call */
private final Method mMethod;
/** argument array */
private final String[] mArgs;
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
public void run() {
try {
mMethod.invoke(null, new Object[] { 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);
}
}
}
Zygote监听请求
再回到ZygoteInit.main方法调用zygoteServer.runSelectLoop
Runnable runSelectLoop(String abiList) {
ArrayList<FileDescriptor> socketFDs = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
// 首先将server socket加入到fds
socketFDs.add(mZygoteSocket.getFileDescriptor());
peers.add(null);
while (true) {
fetchUsapPoolPolicyPropsWithMinInterval();
int[] usapPipeFDs = null;
StructPollfd[] pollFDs = null;
// Allocate enough space for the poll structs, taking into account
// the state of the USAP pool for this Zygote (could be a
// regular Zygote, a WebView Zygote, or an AppZygote).
if (mUsapPoolEnabled) {
...
} else {
//创建socketFDs大小的数据结构StructPollfd(注意:每次循环,都重新创建需要监听的pollFds)
pollFDs = new StructPollfd[socketFDs.size()];
}
/*
* For reasons of correctness the USAP pool pipe and event FDs
* must be processed before the session and server sockets. This
* is to ensure that the USAP pool accounting information is
* accurate when handling other requests like API blacklist
* exemptions.
*/
int pollIndex = 0;
//将socketFDs内容添加到pollFDs中
for (FileDescriptor socketFD : socketFDs) {
pollFDs[pollIndex] = new StructPollfd();
pollFDs[pollIndex].fd = socketFD;
pollFDs[pollIndex].events = (short) POLLIN;
++pollIndex;
}
final int usapPoolEventFDIndex = pollIndex;
...
try {
//监听事件,当有事件到来时被唤醒,没有事件时休眠
Os.poll(pollFDs, -1);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
boolean usapPoolFDRead = false;
//倒序处理,即优先处理已建立链接的信息,后处理新建链接的请求
while (--pollIndex >= 0) {
//检查是否是POLLIN事件
if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
continue;
}
if (pollIndex == 0) {
//pollIndex==0表示收到新的建立通信的请求,建立通信连接
// Zygote server socket
ZygoteConnection newPeer = acceptCommandPeer(abiList);
// 加入到peers和fds, 即下一次循环时会监听这个新的连接
peers.add(newPeer);
socketFDs.add(newPeer.getFileDescriptor());
} else if (pollIndex < usapPoolEventFDIndex) {
// Session socket accepted from the Zygote server socket
//地用到此处说明是前面新的连接发送过来请求,一般就是AMS发送过来创建应用程序的请求
try {
//通过索引找到连接
ZygoteConnection connection = peers.get(pollIndex);
//处理请求
final Runnable command = connection.processOneCommand(this);
// TODO (chriswailes): Is this extra check necessary?
if (mIsForkChild) {
// We're in the child. We should always have a command to run at this
// stage if processOneCommand hasn't called "exec".
if (command == null) {
throw new IllegalStateException("command == null");
}
return command;
} else {
...
}
} catch (Exception e) {
...
} finally {
...
}
} else {
...
}
}
...
}
}
- runSelectLoop中创建一个FileDescriptor集合对象socketFDs,并将mZygoteSocket添加进去
- 然后创建了一个和socketFDs长度相同的StructPollfd数组对象pollFDs(因为后续监听需要传入参数为StructPollfd),并将socketFDs内容添加到pollFDs中
- 调用Os.poll监听事件,当有事件到来时被唤醒,没有事件时休眠;事件分为 2 种
- pollIndex == 0表示Zygote server socket有客户端进行了连接
- 接收连接创建ZygoteConnection对象
- 将getFileDescriptor添加到socketFDs,在下一次循环时就会开始监听这里创建的 ZygoteConnection对象
- pollIndex < usapPoolEventFDIndex表示客户端发送请求需要服务端处理
- 调用ZygoteConnection.processOneCommand处理客户端请求
- pollIndex == 0表示Zygote server socket有客户端进行了连接
就这样Zygote进程在Java世界循环,它会监听来自AMS的应用启动请求,进而处理请求。