voidAndroidRuntime::start(constchar* className, const Vector<String8>& options, bool zygote) { ALOGD(">>>>>> START %s uid %d <<<<<<\n", className != NULL ? className : "(unknown)", getuid()); staticconst String8 startSystemServer("start-system-server"); // Whether this is the primary zygote, meaning the zygote which will fork system server. bool primary_zygote = false; ...... /* start the virtual machine */ JniInvocation jni_invocation; jni_invocation.Init(NULL); JNIEnv* env; //启动虚拟机,主要是关于虚拟机参数的设置 if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) { return; } onVmCreated(env);//空函数,没有任何实现 /* * Register android functions. */ //注册JNI方法 if (startReg(env) < 0) { ALOGE("Unable to register all android natives\n"); return; } /* * We want to call main() with a String array with arguments in it. * At present we have two arguments, the class name and an option string. * Create an array to hold them. */ jclass stringClass; jobjectArray strArray; jstring classNameStr; stringClass = env->FindClass("java/lang/String"); assert(stringClass != NULL); //等价 strArray[0] = "com.android.internal.os.ZygoteInit" strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL); assert(strArray != NULL); classNameStr = env->NewStringUTF(className); assert(classNameStr != NULL); env->SetObjectArrayElement(strArray, 0, classNameStr); //strArray[1]="start-system-server"; //strArray[2]="--abi-list=xxx"; //其中xxx为系统响应的cpu架构类型,比如arm64-v8a for (size_t i = 0; i < options.size(); ++i) { jstring optionsStr = env->NewStringUTF(options.itemAt(i).string()); assert(optionsStr != NULL); env->SetObjectArrayElement(strArray, i + 1, optionsStr); } /* * Start VM. This thread becomes the main thread of the VM, and will * not return until the VM exits. */ //将"com.android.internal.os.ZygoteInit"转换为"com/android/internal/os/ZygoteInit" char* slashClassName = toSlashClassName(className != NULL ? className : ""); jclass startClass = env->FindClass(slashClassName);//找到Zygoteinit if (startClass == NULL) { ALOGE("JavaVM unable to locate class '%s'\n", slashClassName); /* keep going */ } else { //找到这个类后,继续找成员函数main方法的Method ID jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V"); if (startMeth == NULL) { ALOGE("JavaVM unable to find main() in '%s'\n", className); /* keep going */ } else { //通过反射调用ZygoteInit.main()方法 env->CallStaticVoidMethod(startClass, startMeth, strArray); #if 0 if (env->ExceptionCheck()) threadExitUncaughtException(env); #endif } } //释放相应对象的内存空间 free(slashClassName); ALOGD("Shutting down VM\n"); if (mJavaVM->DetachCurrentThread() != JNI_OK) ALOGW("Warning: unable to detach main thread\n"); if (mJavaVM->DestroyJavaVM() != 0) ALOGW("Warning: VM did not shut down cleanly\n"); }
Runnable runSelectLoop(String abiList) { ArrayList<FileDescriptor> socketFDs = newArrayList<>(); ArrayList<ZygoteConnection> peers = newArrayList<>(); //将server socket加入到fds socketFDs.add(mZygoteSocket.getFileDescriptor()); peers.add(null); mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP; while (true) { fetchUsapPoolPolicyPropsWithMinInterval(); mUsapPoolRefillAction = UsapPoolRefillAction.NONE; int[] usapPipeFDs = null; StructPollfd[] pollFDs; //每次循环,都重新创建需要监听的pollFds if (mUsapPoolEnabled) { usapPipeFDs = Zygote.getUsapPipeFDs(); pollFDs = newStructPollfd[socketFDs.size() + 1 + usapPipeFDs.length]; } else { pollFDs = newStructPollfd[socketFDs.size()]; } intpollIndex=0; for (FileDescriptor socketFD : socketFDs) { //关注事件到来 pollFDs[pollIndex] = newStructPollfd(); pollFDs[pollIndex].fd = socketFD; pollFDs[pollIndex].events = (short) POLLIN; ++pollIndex; } finalintusapPoolEventFDIndex= pollIndex; if (mUsapPoolEnabled) { pollFDs[pollIndex] = newStructPollfd(); pollFDs[pollIndex].fd = mUsapPoolEventFD; pollFDs[pollIndex].events = (short) POLLIN; ++pollIndex; // The usapPipeFDs array will always be filled in if the USAP Pool is enabled. assert usapPipeFDs != null; for (int usapPipeFD : usapPipeFDs) { FileDescriptormanagedFd=newFileDescriptor(); managedFd.setInt$(usapPipeFD); pollFDs[pollIndex] = newStructPollfd(); pollFDs[pollIndex].fd = managedFd; pollFDs[pollIndex].events = (short) POLLIN; ++pollIndex; } } int pollTimeoutMs; if (mUsapPoolRefillTriggerTimestamp == INVALID_TIMESTAMP) { pollTimeoutMs = -1; } else { longelapsedTimeMs= System.currentTimeMillis() - mUsapPoolRefillTriggerTimestamp; if (elapsedTimeMs >= mUsapPoolRefillDelayMs) { // The refill delay has elapsed during the period between poll invocations. // We will now check for any currently ready file descriptors before refilling // the USAP pool. pollTimeoutMs = 0; mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP; mUsapPoolRefillAction = UsapPoolRefillAction.DELAYED; } elseif (elapsedTimeMs <= 0) { // This can occur if the clock used by currentTimeMillis is reset, which is // possible because it is not guaranteed to be monotonic. Because we can't tell // how far back the clock was set the best way to recover is to simply re-start // the respawn delay countdown. pollTimeoutMs = mUsapPoolRefillDelayMs; } else { pollTimeoutMs = (int) (mUsapPoolRefillDelayMs - elapsedTimeMs); } } int pollReturnValue; try { //等待事件到来 pollReturnValue = Os.poll(pollFDs, pollTimeoutMs); } catch (ErrnoException ex) { thrownewRuntimeException("poll failed", ex); } if (pollReturnValue == 0) { // The poll returned zero results either when the timeout value has been exceeded // or when a non-blocking poll is issued and no FDs are ready. In either case it // is time to refill the pool. This will result in a duplicate assignment when // the non-blocking poll returns zero results, but it avoids an additional // conditional in the else branch. mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP; mUsapPoolRefillAction = UsapPoolRefillAction.DELAYED; } else { booleanusapPoolFDRead=false; //倒序处理,即优先处理已建立链接的信息,后处理新建链接的请求 while (--pollIndex >= 0) { if ((pollFDs[pollIndex].revents & POLLIN) == 0) { continue; } //server socket最先加入fds,因此这里是server socket收到数据 if (pollIndex == 0) { // Zygote server socket //收到新的建立通信的请求,建立通信连接 ZygoteConnectionnewPeer= acceptCommandPeer(abiList); //加入到peers和fds,即下一次也开监听 peers.add(newPeer); socketFDs.add(newPeer.getFileDescriptor()); } elseif (pollIndex < usapPoolEventFDIndex) { // Session socket accepted from the Zygote server socket //说明接收AMS发送过来创建应用程序的请求,调用processOneCommand来创建新的应用程序进程 try { //有socket连接,创建ZygoteConnection对象,并添加到fds ZygoteConnectionconnection= peers.get(pollIndex); booleanmultipleForksOK= !isUsapPoolEnabled() && ZygoteHooks.isIndefiniteThreadSuspensionSafe(); //处理连接 finalRunnablecommand= connection.processCommand(this, multipleForksOK); // 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 processCommand hasn't called "exec". if (command == null) { thrownewIllegalStateException("command == null"); } return command; } else { // We're in the server - we should never have any commands to run. if (command != null) { thrownewIllegalStateException("command != null"); } // We don't know whether the remote side of the socket was closed or // not until we attempt to read from it from processCommand. This // shows up as a regular POLLIN event in our regular processing // loop. if (connection.isClosedByPeer()) { connection.closeSocket(); peers.remove(pollIndex); socketFDs.remove(pollIndex);//处理完则从fds中移除该文件描述符 } } } catch (Exception e) { ...... } finally { // Reset the child flag, in the event that the child process is a child- // zygote. The flag will not be consulted this loop pass after the // Runnable is returned. mIsForkChild = false; } } ...... }