public class Process { ... private static final String ZYGOTE_SOCKET = "zygote"; ... public static final ProcessStartResult start(final String processClass, final String niceName, int uid, int gid, int[] gids, int debugFlags, int mountExternal, int targetSdkVersion, String seInfo, String[] zygoteArgs) { ... return startViaZygote(processClass, niceName, uid, gid, gids, debugFlags, mountExternal, targetSdkVersion, seInfo, zygoteArgs); ... } ... private static ProcessStartResult startViaZygote(final String processClass, final String niceName, final int uid, final int gid, final int[] gids, int debugFlags, int mountExternal, int targetSdkVersion, String seInfo, String[] extraArgs) throws ZygoteStartFailedEx { ... return zygoteSendArgsAndGetResult(argsForZygote); } ... private static ProcessStartResult zygoteSendArgsAndGetResult(ArrayList<String> args) throws ZygoteStartFailedEx { openZygoteSocketIfNeeded(); ... sZygoteWriter.write(Integer.toString(args.size())); 、 sZygoteWriter.newLine(); int sz = args.size(); for (int i = 0; i < sz; i++) { String arg = args.get(i); if (arg.indexOf('\n') >= 0) { throw new ZygoteStartFailedEx("embedded newlines not allowed"); } sZygoteWriter.write(arg); sZygoteWriter.newLine(); }
sZygoteWriter.flush();
// Should there be a timeout on this? ProcessStartResult result = new ProcessStartResult(); result.pid = sZygoteInputStream.readInt(); if (result.pid < 0) { throw new ZygoteStartFailedEx("fork() failed"); } result.usingWrapper = sZygoteInputStream.readBoolean(); ... } ... private static void openZygoteSocketIfNeeded() throws ZygoteStartFailedEx { ... sZygoteSocket = new LocalSocket(); sZygoteSocket.connect(new LocalSocketAddress(ZYGOTE_SOCKET, LocalSocketAddress.Namespace.RESERVED)); ... } }
int loopCount = GC_LOOP_COUNT; while (true) { int index;
/* * Call gc() before we block in select(). * It's work that has to be done anyway, and it's better * to avoid making every child do it. It will also * madvise() any free memory as a side-effect. * * Don't call it every time, because walking the entire * heap is a lot of overhead to free a few hundred bytes. */ if (loopCount <= 0) { gc(); loopCount = GC_LOOP_COUNT; } else { loopCount--; }
try { fdArray = fds.toArray(fdArray); index = selectReadable(fdArray); } catch (IOException ex) { throw new RuntimeException("Error in select()", ex); }
if (index < 0) { throw new RuntimeException("Error in select()"); } else if (index == 0) { ZygoteConnection newPeer = acceptCommandPeer(); peers.add(newPeer); fds.add(newPeer.getFileDesciptor()); } else { boolean done; done = peers.get(index).runOnce();
if (done) { peers.remove(index); fds.remove(index); } } } }
try { cl = loader.loadClass(className); } 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); }
/* * This throw gets caught in ZygoteInit.main(), which responds * by invoking the exception's run() method. This arrangement * clears up all the stack frames that were required in setting * up the process. */ throw new ZygoteInit.MethodAndArgsCaller(m, argv); }
public static void main(String[] args) { SamplingProfilerIntegration.start();
// CloseGuard defaults to true and can be quite spammy. We // disable it here, but selectively enable it later (via // StrictMode) on debug builds, but using DropBox, not logs. CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
// Set the reporter for event logging in libcore EventLogger.setReporter(new EventLoggingReporter());