Vector<String8> args; if (!className.isEmpty()) { runtime.setClassNameAndArgs(className, argc - i, argv + i); } else { // We're in zygote mode. if (startSystemServer) { args.add(String8("start-system-server")); } .... // In zygote mode, pass all remaining arguments to the zygote // main() method. for (; i < argc; ++i) { args.add(String8(argv[i])); } } //设置进程名称 if (!niceName.isEmpty()) { runtime.setArgv0(niceName.string()); set_process_name(niceName.string()); } // zygote模式,加载ZygoteInit类,这里的args为"start-system-server" if (zygote) { runtime.start("com.android.internal.os.ZygoteInit", args, zygote); } elseif (className) { runtime.start("com.android.internal.os.RuntimeInit", args, zygote); } else { fprintf(stderr, "Error: no class name or --zygote supplied.\n"); app_usage(); LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied."); return10; } }
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. */ char* slashClassName = toSlashClassName(className); jclass startClass = env->FindClass(slashClassName); if (startClass == NULL) { ALOGE("JavaVM unable to locate class '%s'\n", slashClassName); } else { // 获取main函数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 { // 调用main函数 env->CallStaticVoidMethod(startClass, startMeth, strArray); } } 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"); }
/** * In order to avoid leaking descriptors to the Zygote child, * the native code must close the two Zygote socket descriptors * in the child process before it switches from Zygote-root to * the UID and privileges of the application being launched. * * In order to avoid "bad file descriptor" errors when the * two LocalSocket objects are closed, the Posix file * descriptors are released via a dup2() call which closes * the socket and substitutes an open descriptor to /dev/null. */
try { if (pid == 0) { // in child IoUtils.closeQuietly(serverPipeFd); serverPipeFd = null; // 在子进程中,会加载应用代码 handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
// should never get here, the child is expected to either // throw ZygoteInit.MethodAndArgsCaller or exec(). returntrue; } else { // in parent...pid of < 0 means failure IoUtils.closeQuietly(childPipeFd); childPipeFd = null; return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs); } } finally { IoUtils.closeQuietly(childPipeFd); IoUtils.closeQuietly(serverPipeFd); } }
try { finalintuserId= UserHandle.getUserId(app.uid); .... // Start the process. It will either succeed and return a result containing // the PID of the new process, or else throw a RuntimeException.
/** * See com.android.internal.os.ZygoteInit.readArgumentList() * Presently the wire format to the zygote process is: * a) a count of arguments (argc, in essence) * b) a number of newline-separated argument strings equal to count */ finalBufferedWriterwriter= zygoteState.writer; finalDataInputStreaminputStream= zygoteState.inputStream;
for (inti=0; i < sz; i++) { Stringarg= args.get(i); writer.write(arg); writer.newLine(); } // 写入socket writer.flush();
// Should there be a timeout on this? ProcessStartResultresult=newProcessStartResult();
// Always read the entire result from the input stream to avoid leaving // bytes in the stream for future process starts to accidentally stumble // upon. result.pid = inputStream.readInt(); result.usingWrapper = inputStream.readBoolean();
if (parsedArgs.abiListQuery) { return handleAbiListQuery(); } .... /** * In order to avoid leaking descriptors to the Zygote child, * the native code must close the two Zygote socket descriptors * in the child process before it switches from Zygote-root to * the UID and privileges of the application being launched. * * In order to avoid "bad file descriptor" errors when the * two LocalSocket objects are closed, the Posix file * descriptors are released via a dup2() call which closes * the socket and substitutes an open descriptor to /dev/null. */
try { if (pid == 0) { // 子进程继承了zygote进程的FD,需要关闭 IoUtils.closeQuietly(serverPipeFd); serverPipeFd = null; // 继续子进程启动后的一些准备工作 handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr); // should never get here, the child is expected to either // throw ZygoteInit.MethodAndArgsCaller or exec(). returntrue; } else { // in parent...pid of < 0 means failure IoUtils.closeQuietly(childPipeFd); childPipeFd = null; // 将子进程PID写入socket return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs); } } finally { IoUtils.closeQuietly(childPipeFd); IoUtils.closeQuietly(serverPipeFd); } }
调用zygote.forkAndSpecialize创建进程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
publicstaticintforkAndSpecialize(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, int mountExternal, String seInfo, int category, int accessInfo, String niceName, int[] fdsToClose,String instructionSet, String appDataDir, int mountKnoxPoint) { VM_HOOKS.preFork(); // 调用native方法创建进程 intpid= nativeForkAndSpecialize( uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, category, accessInfo, niceName, fdsToClose, instructionSet, appDataDir, mountKnoxPoint); // Enable tracing as soon as possible for the child process. if (pid == 0) { Trace.setTracingEnabled(true);
// Note that this event ends at the end of handleChildProc, Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork"); } VM_HOOKS.postForkCommon(); return pid; }
privatestaticvoidapplicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.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 = newArguments(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); }