先熟悉下:http://blog.csdn.net/jianguo_liao19840726/article/details/15810633
public static void main(String argv[]) { registerZygoteSocket(); preloadClasses(); preloadResources(); if (argv[1].equals("true")) { startSystemServer(); } if (ZYGOTE_FORK_MODE) { runForkMode(); } else { runSelectLoopMode(); } closeServerSocket(); }
1、registerZygoteSocket();注册zygote的socket、即提供socket的服务端
2、preloadClasses(); preloadResources(); 预加载类和资源
3、startSystemServer(); 启动system_server进程
4、运行的孵化器进程的socket的I/O多路复用select循环,等待接受新连接
5、closeServerSocket();关闭socket
先看注册socket,此方法在其注释中已经很好的进行了解释
/** * Registers a server socket for zygote command connections * * @throws RuntimeException when open fails */ private static void registerZygoteSocket() { if (sServerSocket == null) { int fileDesc; try { String env = System.getenv(ANDROID_SOCKET_ENV); fileDesc = Integer.parseInt(env); } catch (RuntimeException ex) { throw new RuntimeException( ANDROID_SOCKET_ENV + " unset or invalid", ex); } try { sServerSocket = new LocalServerSocket( createFileDescriptor(fileDesc)); } catch (IOException ex) { throw new RuntimeException( "Error binding to local socket '" + fileDesc + "'", ex); } } }
private static void preloadClasses() { final VMRuntime runtime = VMRuntime.getRuntime(); InputStream is = ZygoteInit.class.getClassLoader().getResourceAsStream( PRELOADED_CLASSES); //PRELOADED_CLASSES常量值为:preloaded-classes在framework/base下面 BufferedReader br = new BufferedReader(new InputStreamReader(is), 256); int count = 0; String line; while ((line = br.readLine()) != null) { // Skip comments and blank lines. line = line.trim(); if (line.startsWith("#") || line.equals("")) { continue; } try { //通过反射来加载类 Class.forName(line); } } }
startSystemServer();先不讲,放到下一个帖子来讲
private static void runSelectLoopMode() throws MethodAndArgsCaller { ArrayList<FileDescriptor> fds = new ArrayList(); ArrayList<ZygoteConnection> peers = new ArrayList(); FileDescriptor[] fdArray = new FileDescriptor[4]; fds.add(sServerSocket.getFileDescriptor()); peers.add(null); 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); } } } }
static native int selectReadable(FileDescriptor[] fds) throws IOException;
/** * Runs the zygote process's select loop. Accepts new connections as * they happen, and reads commands from connections one spawn-request's * worth at a time.
/** * Invokes select() on the provider array of file descriptors (selecting * for readability only). Array elements of null are ignored. *
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); } }