从源码看Android应用的启动过程

一,应用程序创建

  1. 从AndroidManagerService开始,ActivityManagerService.StartProcessLocked
    源码位置:http://androidxref.com/4.4.4_r1/xref/frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr){
··· ···
 try {
     int uid = app.uid;

     int[] gids = null;
     int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
     if (!app.isolated) {
         int[] permGids = null;
         try {
             final PackageManager pm = mContext.getPackageManager();
             permGids = pm.getPackageGids(app.info.packageName);

Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
 app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion, app.info.seinfo, null);
··· ···
}

首先获取要创建的应用程序的进程uid和用户组gid,然后通过Process类静态成员函数start来创建应用程序进程。

  1. Process类,

Process.start
Process.startViaZygote
Process.zygote

源码位置:
http://androidxref.com/4.4.4_r1/xref/frameworks/base/core/java/android/os/Process.java

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) {
    try {
        return startViaZygote(processClass, niceName, uid, gid, gids,
                debugFlags, mountExternal, targetSdkVersion, seInfo, zygoteArgs);
    } catch (ZygoteStartFailedEx ex) {
        Log.e(LOG_TAG,
                "Starting VM process through Zygote failed");
        throw new RuntimeException(
                "Starting VM process through Zygote failed", ex);
    }
}
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 {
    synchronized(Process.class) {
        ArrayList<String> argsForZygote = new ArrayList<String>();
        // --runtime-init, --setuid=, --setgid=,
        // and --setgroups= must go first
        argsForZygote.add("--runtime-init");
        argsForZygote.add("--setuid=" + uid);
        argsForZygote.add("--setgid=" + gid);
        if ((debugFlags & Zygote.DEBUG_ENABLE_JNI_LOGGING) != 0) {
            argsForZygote.add("--enable-jni-logging");
        }
        if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) {
            argsForZygote.add("--enable-safemode");
        }
        if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) {
            argsForZygote.add("--enable-debugger");
        }
        if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) {
            argsForZygote.add("--enable-checkjni");
        }
        if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
            argsForZygote.add("--enable-assert");
        }
        if (mountExternal == Zygote.MOUNT_EXTERNAL_MULTIUSER) {
            argsForZygote.add("--mount-external-multiuser");
        } else if (mountExternal == Zygote.MOUNT_EXTERNAL_MULTIUSER_ALL) {
            argsForZygote.add("--mount-external-multiuser-all");
        }
        argsForZygote.add("--target-sdk-version=" + targetSdkVersion);

        //TODO optionally enable debuger
        //argsForZygote.add("--enable-debugger");

        // --setgroups is a comma-separated list
        if (gids != null && gids.length > 0) {
            StringBuilder sb = new StringBuilder();
            sb.append("--setgroups=");

            int sz = gids.length;
            for (int i = 0; i < sz; i++) {
                if (i != 0) {
                    sb.append(',');
                }
                sb.append(gids[i]);
            }

            argsForZygote.add(sb.toString());
        }

        if (niceName != null) {
            argsForZygote.add("--nice-name=" + niceName);
        }

        if (seInfo != null) {
            argsForZygote.add("--seinfo=" + seInfo);
        }

        argsForZygote.add(processClass);

        if (extraArgs != null) {
            for (String arg : extraArgs) {
                argsForZygote.add(arg);
            }
        }

        return zygoteSendArgsAndGetResult(argsForZygote);
    }
}

在《Android系统源代码情景分析》一书中用的是2.3的代码,里面的start函数包含supportsProcess来判断系统是否支持Binder进程通信机制,而在本文中使用的是4.4的代码,其中start函数已经删除了该部分,start函数直接调用startViaZygote函数,实际的start已经没有任何用处,至今保留是为了代码兼容。
startViaZygote首先将传入的参数添加到字符串列表argsForZygote中,然后调用zygoteSendArgsAndGetResult函数来请求Zygote进程创建一个新的应用程序进程。

private static ProcessStartResult zygoteSendArgsAndGetResult(ArrayList<String> args)
        throws ZygoteStartFailedEx {
    openZygoteSocketIfNeeded();

    try {
        /**
         * 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
         *
         * After the zygote process reads these it will write the pid of
         * the child or -1 on failure, followed by boolean to
         * indicate whether a wrapper process was used.
         */

        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();
        return result;
    } catch (IOException ex) {
        try {
            if (sZygoteSocket != null) {
                sZygoteSocket.close();
            }
        } catch (IOException ex2) {
            // we're going to fail anyway
            Log.e(LOG_TAG,"I/O exception on routine close", ex2);
        }

        sZygoteSocket = null;
        throw new ZygoteStartFailedEx(ex);
    }
}

首先通过openZygoteSocketIfNeeded()来创建一个LocalSocket对象,用来和Zygote进程通信,然后将传入的参数写道LocalSocket这个对象中,Zygote进程收到参数后就会创建新的应用进程,然后将Pid返回到result,然后这个pid就被返回到AMS(AndroidManagerService)中。
LocalSocket对象的创建过程如下:

private static void openZygoteSocketIfNeeded()
        throws ZygoteStartFailedEx {
    int retryCount;
    if (sPreviousZygoteOpenFailed) {
        /*
         * If we've failed before, expect that we'll fail again and
         * don't pause for retries.
         */
        retryCount = 0;
    } else {
        retryCount = 10;
    }

    /*
     * See bug #811181: Sometimes runtime can make it up before zygote.
     * Really, we'd like to do something better to avoid this condition,
     * but for now just wait a bit...
     */
    for (int retry = 0; (sZygoteSocket == null) && (retry < (retryCount + 1)); retry++ ) {

        if (retry > 0) {
            try {
                Log.i("Zygote", "Zygote not up yet, sleeping...");
                Thread.sleep(ZYGOTE_RETRY_MILLIS);
            } catch (InterruptedException ex) {
                // should never happen
            }
        }
        try {
            sZygoteSocket = new LocalSocket();
            sZygoteSocket.connect(new LocalSocketAddress(ZYGOTE_SOCKET, LocalSocketAddress.Namespace.RESERVED));
            sZygoteInputStream = new DataInputStream(sZygoteSocket.getInputStream());
            sZygoteWriter = new BufferedWriter(new OutputStreamWriter(sZygoteSocket.getOutputStream()), 256);
            Log.i("Zygote", "Process: zygote socket opened");
            sPreviousZygoteOpenFailed = false;
            break;
        } catch (IOException ex) {
            if (sZygoteSocket != null) {
                try {
                    sZygoteSocket.close();
                } catch (IOException ex2) {
                    Log.e(LOG_TAG,"I/O exception on close after exception", ex2);
                }
            }
            sZygoteSocket = null;
        }
    }
    if (sZygoteSocket == null) {
        sPreviousZygoteOpenFailed = true;
        throw new ZygoteStartFailedEx("connect failed");
    }
}

sZygoteSocket是Process类中的一个静态成员变量,首先new一个LocalSocket对象,保存在sZygoteSocket中,然后将之与ZYGOTE_SOCKET建立连接,ZYGOTE_SOCKET(Zygote进程运行后会创建一个名为zygote的Socket,这个Socket与设备文件/dev/socket/zygote绑定在一起,这个Socket的地址就是ZYGOTE_SOCKET),连接过程就是sZygoteSocket在/dev/socket/文件夹下找到zygote文件,然后与之绑定的过程。
然后通过数据流的写入和输出完成了与Zygote进程的通信。

然后再来看下Zygote端:
上面说到,Zygote进程启动后会创建一个名为zygote的Socket,等待AMS与之通信,过程如下:
源码位置:
http://androidxref.com/4.4.4_r1/xref/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
在2.3的代码中名为runSelectLoopMode,在4.4的代码中名字改为了runSelectLoop

private static void runSelectLoop() throws MethodAndArgsCaller {
    ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
    ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
    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);
            }
        }
    }
}

从Socket中读取参数传递到fds,然后解析index,当index>0时,通过runOnce函数来处理Socket请求。
然后来看runOnce的实现,
源码位置:http://androidxref.com/4.4.4_r1/xref/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {

    String args[];
    Arguments parsedArgs = null;
    FileDescriptor[] descriptors;

    try {
        args = readArgumentList();
        descriptors = mSocket.getAncillaryFileDescriptors();
    } catch (IOException ex) {
        Log.w(TAG, "IOException on command socket " + ex.getMessage());
        closeSocket();
        return true;
    }

    if (args == null) {
        // EOF reached.
        closeSocket();
        return true;
    }

    /** the stderr of the most recent request, if avail */
    PrintStream newStderr = null;

    if (descriptors != null && descriptors.length >= 3) {
        newStderr = new PrintStream(
                new FileOutputStream(descriptors[2]));
    }

    int pid = -1;
    FileDescriptor childPipeFd = null;
    FileDescriptor serverPipeFd = null;

    try {
        parsedArgs = new Arguments(args);

        applyUidSecurityPolicy(parsedArgs, peer, peerSecurityContext);
        applyRlimitSecurityPolicy(parsedArgs, peer, peerSecurityContext);
        applyCapabilitiesSecurityPolicy(parsedArgs, peer, peerSecurityContext);
        applyInvokeWithSecurityPolicy(parsedArgs, peer, peerSecurityContext);
        applyseInfoSecurityPolicy(parsedArgs, peer, peerSecurityContext);

        applyDebuggerSystemProperty(parsedArgs);
        applyInvokeWithSystemProperty(parsedArgs);

        int[][] rlimits = null;

        if (parsedArgs.rlimits != null) {
            rlimits = parsedArgs.rlimits.toArray(intArray2d);
        }

        if (parsedArgs.runtimeInit && parsedArgs.invokeWith != null) {
            FileDescriptor[] pipeFds = Libcore.os.pipe();
            childPipeFd = pipeFds[1];
            serverPipeFd = pipeFds[0];
            ZygoteInit.setCloseOnExec(serverPipeFd, true);
        }

        pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                parsedArgs.niceName);
    } catch (IOException ex) {
        logAndPrintError(newStderr, "Exception creating pipe", ex);
    } catch (ErrnoException ex) {
        logAndPrintError(newStderr, "Exception creating pipe", ex);
    } catch (IllegalArgumentException ex) {
        logAndPrintError(newStderr, "Invalid zygote arguments", ex);
    } catch (ZygoteSecurityException ex) {
        logAndPrintError(newStderr,
                "Zygote security policy prevents request: ", ex);
    }

    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().
            return true;
        } 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);
    }
}

首先通过readArgumentList()函数来读取传入的所要创建的进程的参数,将之放到Arguments类型的参数parsedArgs中,然后将parseArgs参数传入到forkAndSpecialize函数,通过forkAndSpecialize函数fork一个子进程,然后检测pid是否为0来判断当前进程是否是子进程,是的话就执行handleChildProc函数来处理子进程,否则就进入下一段代码执行handleParentProc处理父进程(记录子进程pid已经应用描述等信息)。
下面来看处理子进程的流程:
源码位置同上也是在ZygoteConnection.java中

private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
        throws ZygoteInit.MethodAndArgsCaller {

    closeSocket();
    ZygoteInit.closeServerSocket();

    if (descriptors != null) {
        try {
            ZygoteInit.reopenStdio(descriptors[0],
                    descriptors[1], descriptors[2]);

            for (FileDescriptor fd: descriptors) {
                IoUtils.closeQuietly(fd);
            }
            newStderr = System.err;
        } catch (IOException ex) {
            Log.e(TAG, "Error reopening stdio", ex);
        }
    }

    if (parsedArgs.niceName != null) {
        Process.setArgV0(parsedArgs.niceName);
    }

    if (parsedArgs.runtimeInit) {
        if (parsedArgs.invokeWith != null) {
            WrapperInit.execApplication(parsedArgs.invokeWith,
                    parsedArgs.niceName, parsedArgs.targetSdkVersion,
                    pipeFd, parsedArgs.remainingArgs);
        } else {
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
                    parsedArgs.remainingArgs);
        }
    } else {
        String className;
        try {
            className = parsedArgs.remainingArgs[0];
        } catch (ArrayIndexOutOfBoundsException ex) {
            logAndPrintError(newStderr,
                    "Missing required class name argument", null);
            return;
        }

        String[] mainArgs = new String[parsedArgs.remainingArgs.length - 1];
        System.arraycopy(parsedArgs.remainingArgs, 1,
                mainArgs, 0, mainArgs.length);

        if (parsedArgs.invokeWith != null) {
            WrapperInit.execStandalone(parsedArgs.invokeWith,
                    parsedArgs.classpath, className, mainArgs);
        } else {
            ClassLoader cloader;
            if (parsedArgs.classpath != null) {
                cloader = new PathClassLoader(parsedArgs.classpath,
                        ClassLoader.getSystemClassLoader());
            } else {
                cloader = ClassLoader.getSystemClassLoader();
            }

            try {
                ZygoteInit.invokeStaticMain(cloader, className, mainArgs);
            } catch (RuntimeException ex) {
                logAndPrintError(newStderr, "Error starting.", ex);
            }
        }
    }
}

首先是读取描述信息等,这里的nicename不太明白是什么意思,暂时理解为应用信息的一个参数吧,重点是这一段代码:

if (parsedArgs.runtimeInit) {
        if (parsedArgs.invokeWith != null) {
            WrapperInit.execApplication(parsedArgs.invokeWith,
                    parsedArgs.niceName, parsedArgs.targetSdkVersion,
                    pipeFd, parsedArgs.remainingArgs);
        } else {
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
                    parsedArgs.remainingArgs);
        }

runtimeInit这个参数之前在添加参数的时候是加过的,所以这里一定是true,invokeWith 参数是没有添加的,所以执行的是RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,parsedArgs.remainingArgs);也就是运行时初始化。
接着往下看运行时初始化的过程:

public static final void zygoteInit(int targetSdkVersion, String[] argv)
        throws ZygoteInit.MethodAndArgsCaller {
    if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");

    redirectLogStreams();

    commonInit();
    nativeZygoteInit();

    applicationInit(targetSdkVersion, argv);
}

zygoteInitRuntimeInit类的一个静态成员函数,通过commonInit设置新应用的时区和键盘布局等通用信息,通过nativeZygoteInit()在新的应用程序中创建一个Binder线程池,最后通过applicationInit进入application初始化过程,下面分开来看创建进程池和application初始化过程。

二,线程池创建

上面说到通过nativeZygoteInit()在新的进程中创建Binder线程池,在2.3的代码中这个函数也叫做zygoteInitNative,我们还是继续使用4.4的代码来看,从名字可见这是一个jni函数,实现函数名为com_android_internal_os_RuntimeInit_nativeZygoteInit

private static final native void nativeZygoteInit();

源码位置:http://androidxref.com/4.4.4_r1/xref/frameworks/base/core/jni/AndroidRuntime.cpp

static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit();
}

gCurRuntime是一个全局变量,他是在AndroidRuntime类的构造函数中初始化的,Zygote进程启动时会创建一个AppRuntime类,由于AppRuntime类继承了AndroidRuntime类,所以会导致AndroidRuntime类的构造函数被调用,调用过程中gCurRuntime变量会被初始化,指向的就是正在创建的AppRuntime对象。又因为每创建一个应用进程都会fork一个Zygote进程的地址空间,因此每一个应用进程中都存在一个gCurRuntime全局变量。所以这里调用的是AppRuntime的成员函数onZygoteInit()。
源码地址:http://androidxref.com/4.4.4_r1/xref/frameworks/base/cmds/app_process/app_main.cpp

virtual void onZygoteInit()
{
    // Re-enable tracing now that we're no longer in Zygote.
    atrace_set_tracing_enabled(true);

    sp<ProcessState> proc = ProcessState::self();
    ALOGV("App process: starting thread pool.\n");
    proc->startThreadPool();
}

调用当前应用进程中的ProcessState对象的成员函数startThreadPool来启动一个Binder线程池;
ProcessState.startThreadPool();
源码位置:http://androidxref.com/4.4.4_r1/xref/frameworks/native/libs/binder/ProcessState.cpp

void ProcessState::startThreadPool()
{
   AutoMutex _l(mLock);
   if (!mThreadPoolStarted) {
      mThreadPoolStarted = true;
      spawnPooledThread(true);
    }
}

Android系统中每个支持Binder进程间通信的进程都有唯一一个ProcessState对象,当这个对象的成员函数startThreadPool第一次被调用时就会启动Binder进程池,并且将mThreadPoolStarted的值设为true,避免之后重复启动。

这里可以看到先将mThreadStarted参数设置为true,避免之后重复启动线程池,然后调用spawnPooledThread函数。

void ProcessState::spawnPooledThread(bool isMain)
{
  if (mThreadPoolStarted) {
      String8 name = makeBinderThreadName();
      ALOGV("Spawning new pooled thread, name=%s\n", name.string());
      sp<Thread> t = new PoolThread(isMain);
      t->run(name.string());
   }
}

上一段代码可见这里的isMain参数为true,表示:线程t是进程主动创建来加如到它的Binder线程池的,以区别于Binder驱动程序请求进程创建新的线程来加入到它的Binder线程池的情况。
new一个PoolThread对象,然后调用它的成员函数run,并将线程名传入作为参数。
PoolThread类继承了线程类Thread,并且重写了它的线程入口成员函数threadLoop,改写后如下:

class PoolThread : public Thread
{
public:
  PoolThread(bool isMain)
      : mIsMain(isMain)
  {
  }

protected:
  virtual bool threadLoop()
  {
      IPCThreadState::self()->joinThreadPool(mIsMain);
      return false;
  }

  const bool mIsMain;
};

调用了IPCThreadState对象的成员函数joinThreadPool将当前线程注册到Binder驱动程序中去成为一个Binder线程,以便Binder驱动程序可以分发进程间通信请求给它处理,joinThreadPool的代码如下:
源码路径:http://androidxref.com/4.4.4_r1/xref/frameworks/native/libs/binder/IPCThreadState.cpp

void IPCThreadState::joinThreadPool(bool isMain)
{
  LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid());

  mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);

  // This thread may have been spawned by a thread that was in the background
  // scheduling group, so first we will make sure it is in the foreground
  // one to avoid performing an initial transaction in the background.
  set_sched_policy(mMyThreadId, SP_FOREGROUND);

  status_t result;
  do {
      processPendingDerefs();
      // now get the next command to be processed, waiting if necessary
      result = getAndExecuteCommand();

      if (result < NO_ERROR && result != TIMED_OUT && result != -ECONNREFUSED && result != -EBADF) {
          ALOGE("getAndExecuteCommand(fd=%d) returned unexpected error %d, aborting",
                mProcess->mDriverFD, result);
          abort();
      }

      // Let this thread exit the thread pool if it is no longer
      // needed and it is not the main process thread.
      if(result == TIMED_OUT && !isMain) {
          break;
      }
  } while (result != -ECONNREFUSED && result != -EBADF);

  LOG_THREADPOOL("**** THREAD %p (PID %d) IS LEAVING THE THREAD POOL err=%p\n",
      (void*)pthread_self(), getpid(), (void*)result);

  mOut.writeInt32(BC_EXIT_LOOPER);
  talkWithDriver(false);
}

mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);这里的isMain值为true,所以将BC_ENTER_LOOPER命令写入到IPCThreadState类内部的命令协议缓冲区mOut中,最后通过talkWithDriver将命令发送给Binder驱动程序,完成注册。

第一部分中说到Zygote收到AMS传来的参数和命令之后会执行两个动作,一个是通过nativeZygoteInit()来启动线程池,另一个就是接下来要说的通过applicationInit完成application初始化的过程。

三,Application初始化

applicationInit代码如下:
源码路径:http://androidxref.com/4.4.4_r1/xref/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java#applicationInit

 private static void applicationInit(int targetSdkVersion, String[] argv)
        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 = new Arguments(argv);
    } catch (IllegalArgumentException ex) {
        Slog.e(TAG, ex.getMessage());
        // let the process exit
        return;
    }

    // Remaining arguments are passed to the start class's static main
    invokeStaticMain(args.startClass, args.startArgs);
}

重点是最后一行,获取传入参数后调用invokeStaticMain函数:

private static void invokeStaticMain(String className, String[] argv)
        throws ZygoteInit.MethodAndArgsCaller {
    Class<?> cl;

    try {
        cl = Class.forName(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);
}

通过第一部分AMS指定参数可知,这里传入的className的值为android.app.ActivityThread,其中这行代码cl = Class.forName(className);使用装载当前类的类装载器来装载android.app.ActivityThread类,在2.3版本的代码中此处为cl = loader.loadClass(className)二者的区别在于后者只是将信息装载给jvm,需要手动制定装载器的实例。
然后获取android.app.ActivityThreadmain函数保存到Method对象m中,最后将这个method封装到一个MethodAndArgsCaller对象中,并将这个MethodAndArgsCaller对象作为一个异常抛给当前应用进程处理,

public static void main(String argv[]) {
    try {
        ··· ···
    }catch (MethodAndArgsCaller caller) {
            caller.run();
            }

当前进程收到异常后直接运行MethodAndArgsCaller对象的run()方法。
MethodAndArgsCaller.run():
源码路径:http://androidxref.com/4.4.4_r1/xref/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

public static class MethodAndArgsCaller extends Exception
        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);
        }
    }
}

因为这个mMethod对象是封装的android.app.ActivityThreadmain方法,所以这里要做的就是main方法的调用。

兜兜转转一大圈回来之后还是调用android.app.ActivityThreadmain方法,那么为什么没有在第一步中直接调用main方法呢?因为新应用程序的一开始需要初始化运行时库以及创建Binder线程池,为了利用java的异常处理机制清理掉前面的调用堆栈,所以要间接的调用main方法。

然后来看main方法的具体实现:
http://androidxref.com/4.4.4_r1/xref/frameworks/base/core/java/android/app/ActivityThread.java

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());
    Security.addProvider(new AndroidKeyStoreProvider());
    Process.setArgV0("<pre-initialized>");
    Looper.prepareMainLooper();
    ActivityThread thread = new ActivityThread();
    thread.attach(false);
    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }
    AsyncTask.init();
    if (false) {
        Looper.myLooper().setMessageLogging(new
                LogPrinter(Log.DEBUG, "ActivityThread"));
    }
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

通过prepareMainLooper()函数创建一个消息循环,然后new一个ActivityThread:thread,并调用自身的attach()方法,通过getHandler()获取thread的Handle对象,然后再调用loop()函数使thread回到前面的消息循环中,让ActivityThread类一直处于等待消息的工作状态。
消息循环很容易理解,那么attach()类做了什么呢?
http://androidxref.com/4.4.4_r1/xref/frameworks/base/core/java/android/app/ActivityThread.java#attach

private void attach(boolean system) {
    sCurrentActivityThread = this;
    mSystemThread = system;
    if (!system) {
        ViewRootImpl.addFirstDrawHandler(new Runnable() {
            @Override
            public void run() {
                ensureJitEnabled();
            }
        });
        android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                UserHandle.myUserId());
        RuntimeInit.setApplicationObject(mAppThread.asBinder());
        IActivityManager mgr = ActivityManagerNative.getDefault();
        try {
            mgr.attachApplication(mAppThread);
        } catch (RemoteException ex) {
            // Ignore
        }
    } else {
        // Don't set application object here -- if the system crashes,
        // we can't display an alert, we just want to die die die.
        android.ddm.DdmHandleAppName.setAppName("system_process",
                                                UserHandle.myUserId());
        try {
            mInstrumentation = new Instrumentation();
            ContextImpl context = ContextImpl.createAppContext(
                    this, getSystemContext().mPackageInfo);
            Application app = Instrumentation.newApplication(Application.class, context);
            mAllApplications.add(app);
            mInitialApplication = app;
            app.onCreate();
        } catch (Exception e) {
            throw new RuntimeException(
                    "Unable to instantiate Application():" + e.toString(), e);
        }
    }

    // add dropbox logging to libcore
    DropBox.setReporter(new DropBoxReporter());

    ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            synchronized (mResourcesManager) {
                // We need to apply this change to the resources
                // immediately, because upon returning the view
                // hierarchy will be informed about it.
                if (mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null)) {
                    // This actually changed the resources!  Tell
                    // everyone about it.
                    if (mPendingConfiguration == null ||
                            mPendingConfiguration.isOtherSeqNewer(newConfig)) {
                        mPendingConfiguration = newConfig;

                        sendMessage(H.CONFIGURATION_CHANGED, newConfig);
                    }
                }
            }
        }
        @Override
        public void onLowMemory() {
        }
        @Override
        public void onTrimMemory(int level) {
        }
    });
}

从上一步代码可见传入参数是false,那么将执行第一个if判断里的内容,直接看核心代码:

 IActivityManager mgr = ActivityManagerNative.getDefault();
        try {
            mgr.attachApplication(mAppThread);
        } catch (RemoteException ex) {
            // Ignore

首先实例化一个IActivityManager对象,然后调用它的attachApplication方法,来看下这个方法具体实现:
http://androidxref.com/4.4.4_r1/xref/frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

public final void attachApplication(IApplicationThread thread) {
    synchronized (this) {
        int callingPid = Binder.getCallingPid();
        final long origId = Binder.clearCallingIdentity();
        attachApplicationLocked(thread, callingPid);
        Binder.restoreCallingIdentity(origId);
    }
}

主要是调用了attachApplicationLocked函数:

private final boolean attachApplicationLocked(IApplicationThread thread,
        int pid) {
....
try {
    ...     
    thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
            profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
            app.instrumentationUiAutomationConnection, testMode,
            mBinderTransactionTrackingEnabled, enableTrackAllocation,
            isRestrictedBackupMode || !normalMode, app.persistent,
            new Configuration(mConfiguration), app.compat,
            getCommonServicesLocked(app.isolated),
            mCoreSettingsObserver.getCoreSettingsLocked());
 
//...
} catch (Exception e) {
    return false;
}
 
....

其中调用的thread.bindApplication()实现如下:
源码路径:http://androidxref.com/4.4.4_r1/xref/frameworks/base/core/java/android/app/ActivityThread.java

public final void bindApplication(String processName,
            ApplicationInfo appInfo, List<ProviderInfo> providers,
            ComponentName instrumentationName, String profileFile,
            ParcelFileDescriptor profileFd, boolean autoStopProfiler,
            Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
            IUiAutomationConnection instrumentationUiConnection, int debugMode,
            boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent,
            Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
            Bundle coreSettings) {

        if (services != null) {
            // Setup the service cache in the ServiceManager
            ServiceManager.initServiceCache(services);
        }

        setCoreSettings(coreSettings);

        AppBindData data = new AppBindData();
        data.processName = processName;
        data.appInfo = appInfo;
        data.providers = providers;
        data.instrumentationName = instrumentationName;
        data.instrumentationArgs = instrumentationArgs;
        data.instrumentationWatcher = instrumentationWatcher;
        data.instrumentationUiAutomationConnection = instrumentationUiConnection;
        data.debugMode = debugMode;
        data.enableOpenGlTrace = enableOpenGlTrace;
        data.restrictedBackupMode = isRestrictedBackupMode;
        data.persistent = persistent;
        data.config = config;
        data.compatInfo = compatInfo;
        data.initProfileFile = profileFile;
        data.initProfileFd = profileFd;
        data.initAutoStopProfiler = false;
        sendMessage(H.BIND_APPLICATION, data);
    }

先把参数初始化,然后sendMessage到Handler中处理,

public void handleMessage(Message msg) {
        if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
        switch (msg.what) {
            case BIND_APPLICATION:
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
                AppBindData data = (AppBindData)msg.obj;
                handleBindApplication(data);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                break;
            
        }
        if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
}

在handler处理中调用了handleBindApplication函数:

private void handleBindApplication(AppBindData data) {
    mBoundApplication = data;
    mConfiguration = new Configuration(data.config);
    mCompatConfiguration = new Configuration(data.config);

    mProfiler = new Profiler();
    mProfiler.profileFile = data.initProfileFile;
    mProfiler.profileFd = data.initProfileFd;
    mProfiler.autoStopProfiler = data.initAutoStopProfiler;

    // send up app name; do this *before* waiting for debugger
    Process.setArgV0(data.processName);
    android.ddm.DdmHandleAppName.setAppName(data.processName,
                                            UserHandle.myUserId());

    if (data.persistent) {
        // Persistent processes on low-memory devices do not get to
        // use hardware accelerated drawing, since this can add too much
        // overhead to the process.
        if (!ActivityManager.isHighEndGfx()) {
            HardwareRenderer.disable(false);
        }
    }

    if (mProfiler.profileFd != null) {
        mProfiler.startProfiling();
    }

    // If the app is Honeycomb MR1 or earlier, switch its AsyncTask
    // implementation to use the pool executor.  Normally, we use the
    // serialized executor as the default. This has to happen in the
    // main thread so the main looper is set right.
    if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) {
        AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
    }

    /*
     * Before spawning a new process, reset the time zone to be the system time zone.
     * This needs to be done because the system time zone could have changed after the
     * the spawning of this process. Without doing this this process would have the incorrect
     * system time zone.
     */
    TimeZone.setDefault(null);

    /*
     * Initialize the default locale in this process for the reasons we set the time zone.
     */
    Locale.setDefault(data.config.locale);

    /*
     * Update the system configuration since its preloaded and might not
     * reflect configuration changes. The configuration object passed
     * in AppBindData can be safely assumed to be up to date
     */
    mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo);
    mCurDefaultDisplayDpi = data.config.densityDpi;
    applyCompatConfiguration(mCurDefaultDisplayDpi);

    data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);

    /**
     * Switch this process to density compatibility mode if needed.
     */
    if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
            == 0) {
        mDensityCompatMode = true;
        Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
    }
    updateDefaultDensity();

    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
    if (!Process.isIsolated()) {
        final File cacheDir = appContext.getCacheDir();

        if (cacheDir != null) {
            // Provide a usable directory for temporary files
            System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());

            setupGraphicsSupport(data.info, cacheDir);
        } else {
            Log.e(TAG, "Unable to setupGraphicsSupport due to missing cache directory");
        }
    }
    /**
     * For system applications on userdebug/eng builds, log stack
     * traces of disk and network access to dropbox for analysis.
     */
    if ((data.appInfo.flags &
         (ApplicationInfo.FLAG_SYSTEM |
          ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0) {
        StrictMode.conditionallyEnableDebugLogging();
    }

    /**
     * For apps targetting SDK Honeycomb or later, we don't allow
     * network usage on the main event loop / UI thread.
     *
     * Note to those grepping:  this is what ultimately throws
     * NetworkOnMainThreadException ...
     */
    if (data.appInfo.targetSdkVersion > 9) {
        StrictMode.enableDeathOnNetwork();
    }

    if (data.debugMode != IApplicationThread.DEBUG_OFF) {
        // XXX should have option to change the port.
        Debug.changeDebugPort(8100);
        if (data.debugMode == IApplicationThread.DEBUG_WAIT) {
            Slog.w(TAG, "Application " + data.info.getPackageName()
                  + " is waiting for the debugger on port 8100...");

            IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
                mgr.showWaitingForDebugger(mAppThread, true);
            } catch (RemoteException ex) {
            }

            Debug.waitForDebugger();

            try {
                mgr.showWaitingForDebugger(mAppThread, false);
            } catch (RemoteException ex) {
            }

        } else {
            Slog.w(TAG, "Application " + data.info.getPackageName()
                  + " can be debugged on port 8100...");
        }
    }

    // Enable OpenGL tracing if required
    if (data.enableOpenGlTrace) {
        GLUtils.setTracingLevel(1);
    }

    // Allow application-generated systrace messages if we're debuggable.
    boolean appTracingAllowed = (data.appInfo.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0;
    Trace.setAppTracingAllowed(appTracingAllowed);

    /**
     * Initialize the default http proxy in this process for the reasons we set the time zone.
     */
    IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
    if (b != null) {
        // In pre-boot mode (doing initial launch to collect password), not
        // all system is up.  This includes the connectivity service, so don't
        // crash if we can't get it.
        IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
        try {
            ProxyProperties proxyProperties = service.getProxy();
            Proxy.setHttpProxySystemProperty(proxyProperties);
        } catch (RemoteException e) {}
    }

    if (data.instrumentationName != null) {
        InstrumentationInfo ii = null;
        try {
            ii = appContext.getPackageManager().
                getInstrumentationInfo(data.instrumentationName, 0);
        } catch (PackageManager.NameNotFoundException e) {
        }
        if (ii == null) {
            throw new RuntimeException(
                "Unable to find instrumentation info for: "
                + data.instrumentationName);
        }

        mInstrumentationAppDir = ii.sourceDir;
        mInstrumentationAppLibraryDir = ii.nativeLibraryDir;
        mInstrumentationAppPackage = ii.packageName;
        mInstrumentedAppDir = data.info.getAppDir();
        mInstrumentedAppLibraryDir = data.info.getLibDir();

        ApplicationInfo instrApp = new ApplicationInfo();
        instrApp.packageName = ii.packageName;
        instrApp.sourceDir = ii.sourceDir;
        instrApp.publicSourceDir = ii.publicSourceDir;
        instrApp.dataDir = ii.dataDir;
        instrApp.nativeLibraryDir = ii.nativeLibraryDir;
        LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
                appContext.getClassLoader(), false, true);
        ContextImpl instrContext = ContextImpl.createAppContext(this, pi);

        try {
            java.lang.ClassLoader cl = instrContext.getClassLoader();
            mInstrumentation = (Instrumentation)
                cl.loadClass(data.instrumentationName.getClassName()).newInstance();
        } catch (Exception e) {
            throw new RuntimeException(
                "Unable to instantiate instrumentation "
                + data.instrumentationName + ": " + e.toString(), e);
        }

        mInstrumentation.init(this, instrContext, appContext,
               new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher,
               data.instrumentationUiAutomationConnection);

        if (mProfiler.profileFile != null && !ii.handleProfiling
                && mProfiler.profileFd == null) {
            mProfiler.handlingProfiling = true;
            File file = new File(mProfiler.profileFile);
            file.getParentFile().mkdirs();
            Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
        }

    } else {
        mInstrumentation = new Instrumentation();
    }

    if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
        dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
    }

    // Allow disk access during application and provider setup. This could
    // block processing ordered broadcasts, but later processing would
    // probably end up doing the same disk access.
    final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
    try {
        // If the app is being launched for full backup or restore, bring it up in
        // a restricted environment with the base application class.
        Application app = data.info.makeApplication(data.restrictedBackupMode, null);
        mInitialApplication = app;

        // don't bring up providers in restricted mode; they may depend on the
        // app's custom Application class
        if (!data.restrictedBackupMode) {
            List<ProviderInfo> providers = data.providers;
            if (providers != null) {
                installContentProviders(app, providers);
                // For process that contains content providers, we want to
                // ensure that the JIT is enabled "at some point".
                mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
            }
        }

        // Do this after providers, since instrumentation tests generally start their
        // test thread at this point, and we don't want that racing.
        try {
            mInstrumentation.onCreate(data.instrumentationArgs);
        }
        catch (Exception e) {
            throw new RuntimeException(
                "Exception thrown in onCreate() of "
                + data.instrumentationName + ": " + e.toString(), e);
        }

        try {
            mInstrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
            if (!mInstrumentation.onException(app, e)) {
                throw new RuntimeException(
                    "Unable to create application " + app.getClass().getName()
                    + ": " + e.toString(), e);
            }
        }
    } finally {
        StrictMode.setThreadPolicy(savedPolicy);
    }
}

代码很长,核心部分如下:

private void handleBindApplication(AppBindData data) {
 
        mBoundApplication = data;
 
····
        Application app;
        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
        final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy();
        try {
           
            app = data.info.makeApplication(data.restrictedBackupMode, null);
····
            try {
                mInstrumentation.onCreate(data.instrumentationArgs);
            }
 
            try {
                mInstrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
                if (!mInstrumentation.onException(app, e)) {
                    throw new RuntimeException(
                      "Unable to create application " + app.getClass().getName()
                      + ": " + e.toString(), e);
                }
            }
····
 
}

通过makeApplication函数创建一个Application:
http://androidxref.com/4.4.4_r1/xref/frameworks/base/core/java/android/app/LoadedApk.java

public Application makeApplication(boolean forceDefaultAppClass,
        Instrumentation instrumentation) {
    if (mApplication != null) {
        return mApplication;
    }

    Application app = null;

    String appClass = mApplicationInfo.className;
    if (forceDefaultAppClass || (appClass == null)) {
        appClass = "android.app.Application";
    }

    try {
        java.lang.ClassLoader cl = getClassLoader();
        ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
        app = mActivityThread.mInstrumentation.newApplication(
                cl, appClass, appContext);
        appContext.setOuterContext(app);
    } catch (Exception e) {
        if (!mActivityThread.mInstrumentation.onException(app, e)) {
            throw new RuntimeException(
                "Unable to instantiate application " + appClass
                + ": " + e.toString(), e);
        }
    }
    mActivityThread.mAllApplications.add(app);
    mApplication = app;

    if (instrumentation != null) {
        try {
            instrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
            if (!instrumentation.onException(app, e)) {
                throw new RuntimeException(
                    "Unable to create application " + app.getClass().getName()
                    + ": " + e.toString(), e);
            }
        }
    }

    return app;
}

获取android.app.Application的完整类名,获取类加载器对象以及上下文,最后调用Instrumentation类的newApplication对象:
http://androidxref.com/4.4.4_r1/xref/frameworks/base/core/java/android/app/Instrumentation.java

public Application newApplication(ClassLoader cl, String className, Context context)
        throws InstantiationException, IllegalAccessException,
        ClassNotFoundException {
    return newApplication(cl.loadClass(className), context);
}

static public Application newApplication(Class<?> clazz, Context context)
        throws InstantiationException, IllegalAccessException,
        ClassNotFoundException {
    Application app = (Application)clazz.newInstance();
    app.attach(context);
    return app;
}

这里通过反射的方式,创建了 Application 类的实例,并且绑定了 Application 的上下文,注意一下:在handleBindApplication中调用makeApplication时候传入的最后一个参数是null,所以这里的 instrumentation 对象为空,并不会去执行makeApplication中的最后一个if判断中的callApplicationOnCreate(),所以makeApplication中直接返回了新建的这个app变量也就是Application类到handBindApplication中然后执行mInstrumentation.callApplicationOnCreate(app);这行代码,直接调用Application类的OnCreat()方法,而这个方法就是我们写代码的时候主函数中重写的ApplicationOnCreat()方法.

然后接下来就是执行我们写的应用内部的代码了。
至此我们的应用终于正常启动起来!!!!!!!!!!

4,附录:Application类的源码:

上源码
package android.app;

import android.annotation.CallSuper;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentCallbacks;
import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.util.Log;
import android.view.autofill.AutofillManager;

import java.util.ArrayList;

/**
 * Base class for maintaining global application state. You can provide your own
 * implementation by creating a subclass and specifying the fully-qualified name
 * of this subclass as the <code>"android:name"</code> attribute in your
 * AndroidManifest.xml's <code>&lt;application&gt;</code> tag. The Application
 * class, or your subclass of the Application class, is instantiated before any
 * other class when the process for your application/package is created.
 *
 * <p class="note"><strong>Note: </strong>There is normally no need to subclass
 * Application.  In most situations, static singletons can provide the same
 * functionality in a more modular way.  If your singleton needs a global
 * context (for example to register broadcast receivers), include
 * {@link android.content.Context#getApplicationContext() Context.getApplicationContext()}
 * as a {@link android.content.Context} argument when invoking your singleton's
 * <code>getInstance()</code> method.
 * </p>
 */
public class Application extends ContextWrapper implements ComponentCallbacks2 {
    private static final String TAG = "Application";
    @UnsupportedAppUsage
    private ArrayList<ComponentCallbacks> mComponentCallbacks =
            new ArrayList<ComponentCallbacks>();
    @UnsupportedAppUsage
    private ArrayList<ActivityLifecycleCallbacks> mActivityLifecycleCallbacks =
            new ArrayList<ActivityLifecycleCallbacks>();
    @UnsupportedAppUsage
    private ArrayList<OnProvideAssistDataListener> mAssistCallbacks = null;

    /** @hide */
    @UnsupportedAppUsage
    public LoadedApk mLoadedApk;

    public interface ActivityLifecycleCallbacks {

        /**
         * Called as the first step of the Activity being created. This is always called before
         * {@link Activity#onCreate}.
         */
        default void onActivityPreCreated(@NonNull Activity activity,
                @Nullable Bundle savedInstanceState) {
        }

        /**
         * Called when the Activity calls {@link Activity#onCreate super.onCreate()}.
         */
        void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState);

        /**
         * Called as the last step of the Activity being created. This is always called after
         * {@link Activity#onCreate}.
         */
        default void onActivityPostCreated(@NonNull Activity activity,
                @Nullable Bundle savedInstanceState) {
        }

        /**
         * Called as the first step of the Activity being started. This is always called before
         * {@link Activity#onStart}.
         */
        default void onActivityPreStarted(@NonNull Activity activity) {
        }

        /**
         * Called when the Activity calls {@link Activity#onStart super.onStart()}.
         */
        void onActivityStarted(@NonNull Activity activity);

        /**
         * Called as the last step of the Activity being started. This is always called after
         * {@link Activity#onStart}.
         */
        default void onActivityPostStarted(@NonNull Activity activity) {
        }

        /**
         * Called as the first step of the Activity being resumed. This is always called before
         * {@link Activity#onResume}.
         */
        default void onActivityPreResumed(@NonNull Activity activity) {
        }

        /**
         * Called when the Activity calls {@link Activity#onResume super.onResume()}.
         */
        void onActivityResumed(@NonNull Activity activity);

        /**
         * Called as the last step of the Activity being resumed. This is always called after
         * {@link Activity#onResume} and {@link Activity#onPostResume}.
         */
        default void onActivityPostResumed(@NonNull Activity activity) {
        }

        /**
         * Called as the first step of the Activity being paused. This is always called before
         * {@link Activity#onPause}.
         */
        default void onActivityPrePaused(@NonNull Activity activity) {
        }

        /**
         * Called when the Activity calls {@link Activity#onPause super.onPause()}.
         */
        void onActivityPaused(@NonNull Activity activity);

        /**
         * Called as the last step of the Activity being paused. This is always called after
         * {@link Activity#onPause}.
         */
        default void onActivityPostPaused(@NonNull Activity activity) {
        }

        /**
         * Called as the first step of the Activity being stopped. This is always called before
         * {@link Activity#onStop}.
         */
        default void onActivityPreStopped(@NonNull Activity activity) {
        }

        /**
         * Called when the Activity calls {@link Activity#onStop super.onStop()}.
         */
        void onActivityStopped(@NonNull Activity activity);

        /**
         * Called as the last step of the Activity being stopped. This is always called after
         * {@link Activity#onStop}.
         */
        default void onActivityPostStopped(@NonNull Activity activity) {
        }

        /**
         * Called as the first step of the Activity saving its instance state. This is always
         * called before {@link Activity#onSaveInstanceState}.
         */
        default void onActivityPreSaveInstanceState(@NonNull Activity activity,
                @NonNull Bundle outState) {
        }

        /**
         * Called when the Activity calls
         * {@link Activity#onSaveInstanceState super.onSaveInstanceState()}.
         */
        void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState);

        /**
         * Called as the last step of the Activity saving its instance state. This is always
         * called after{@link Activity#onSaveInstanceState}.
         */
        default void onActivityPostSaveInstanceState(@NonNull Activity activity,
                @NonNull Bundle outState) {
        }

        /**
         * Called as the first step of the Activity being destroyed. This is always called before
         * {@link Activity#onDestroy}.
         */
        default void onActivityPreDestroyed(@NonNull Activity activity) {
        }

        /**
         * Called when the Activity calls {@link Activity#onDestroy super.onDestroy()}.
         */
        void onActivityDestroyed(@NonNull Activity activity);

        /**
         * Called as the last step of the Activity being destroyed. This is always called after
         * {@link Activity#onDestroy}.
         */
        default void onActivityPostDestroyed(@NonNull Activity activity) {
        }
    }

    /**
     * Callback interface for use with {@link Application#registerOnProvideAssistDataListener}
     * and {@link Application#unregisterOnProvideAssistDataListener}.
     */
    public interface OnProvideAssistDataListener {
        /**
         * This is called when the user is requesting an assist, to build a full
         * {@link Intent#ACTION_ASSIST} Intent with all of the context of the current
         * application.  You can override this method to place into the bundle anything
         * you would like to appear in the {@link Intent#EXTRA_ASSIST_CONTEXT} part
         * of the assist Intent.
         */
        public void onProvideAssistData(Activity activity, Bundle data);
    }

    public Application() {
        super(null);
    }

    /**
     * Called when the application is starting, before any activity, service,
     * or receiver objects (excluding content providers) have been created.
     *
     * <p>Implementations should be as quick as possible (for example using
     * lazy initialization of state) since the time spent in this function
     * directly impacts the performance of starting the first activity,
     * service, or receiver in a process.</p>
     *
     * <p>If you override this method, be sure to call {@code super.onCreate()}.</p>
     *
     * <p class="note">Be aware that direct boot may also affect callback order on
     * Android {@link android.os.Build.VERSION_CODES#N} and later devices.
     * Until the user unlocks the device, only direct boot aware components are
     * allowed to run. You should consider that all direct boot unaware
     * components, including such {@link android.content.ContentProvider}, are
     * disabled until user unlock happens, especially when component callback
     * order matters.</p>
     */
    @CallSuper
    public void onCreate() {
    }

    /**
     * This method is for use in emulated process environments.  It will
     * never be called on a production Android device, where processes are
     * removed by simply killing them; no user code (including this callback)
     * is executed when doing so.
     */
    @CallSuper
    public void onTerminate() {
    }

    @CallSuper
    public void onConfigurationChanged(@NonNull Configuration newConfig) {
        Object[] callbacks = collectComponentCallbacks();
        if (callbacks != null) {
            for (int i=0; i<callbacks.length; i++) {
                ((ComponentCallbacks)callbacks[i]).onConfigurationChanged(newConfig);
            }
        }
    }

    @CallSuper
    public void onLowMemory() {
        Object[] callbacks = collectComponentCallbacks();
        if (callbacks != null) {
            for (int i=0; i<callbacks.length; i++) {
                ((ComponentCallbacks)callbacks[i]).onLowMemory();
            }
        }
    }

    @CallSuper
    public void onTrimMemory(int level) {
        Object[] callbacks = collectComponentCallbacks();
        if (callbacks != null) {
            for (int i=0; i<callbacks.length; i++) {
                Object c = callbacks[i];
                if (c instanceof ComponentCallbacks2) {
                    ((ComponentCallbacks2)c).onTrimMemory(level);
                }
            }
        }
    }

    public void registerComponentCallbacks(ComponentCallbacks callback) {
        synchronized (mComponentCallbacks) {
            mComponentCallbacks.add(callback);
        }
    }

    public void unregisterComponentCallbacks(ComponentCallbacks callback) {
        synchronized (mComponentCallbacks) {
            mComponentCallbacks.remove(callback);
        }
    }

    public void registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {
        synchronized (mActivityLifecycleCallbacks) {
            mActivityLifecycleCallbacks.add(callback);
        }
    }

    public void unregisterActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {
        synchronized (mActivityLifecycleCallbacks) {
            mActivityLifecycleCallbacks.remove(callback);
        }
    }

    public void registerOnProvideAssistDataListener(OnProvideAssistDataListener callback) {
        synchronized (this) {
            if (mAssistCallbacks == null) {
                mAssistCallbacks = new ArrayList<OnProvideAssistDataListener>();
            }
            mAssistCallbacks.add(callback);
        }
    }

    public void unregisterOnProvideAssistDataListener(OnProvideAssistDataListener callback) {
        synchronized (this) {
            if (mAssistCallbacks != null) {
                mAssistCallbacks.remove(callback);
            }
        }
    }

    /**
     * Returns the name of the current process. A package's default process name
     * is the same as its package name. Non-default processes will look like
     * "$PACKAGE_NAME:$NAME", where $NAME corresponds to an android:process
     * attribute within AndroidManifest.xml.
     */
    public static String getProcessName() {
        return ActivityThread.currentProcessName();
    }

    // ------------------ Internal API ------------------

    /**
     * @hide
     */
    @UnsupportedAppUsage
    /* package */ final void attach(Context context) {
        attachBaseContext(context);
        mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
    }

    @UnsupportedAppUsage
        /* package */ void dispatchActivityPreCreated(@NonNull Activity activity,
            @Nullable Bundle savedInstanceState) {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i = 0; i < callbacks.length; i++) {
                ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPreCreated(activity,
                        savedInstanceState);
            }
        }
    }

    @UnsupportedAppUsage
    /* package */ void dispatchActivityCreated(@NonNull Activity activity,
            @Nullable Bundle savedInstanceState) {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i=0; i<callbacks.length; i++) {
                ((ActivityLifecycleCallbacks)callbacks[i]).onActivityCreated(activity,
                        savedInstanceState);
            }
        }
    }

    @UnsupportedAppUsage
        /* package */ void dispatchActivityPostCreated(@NonNull Activity activity,
            @Nullable Bundle savedInstanceState) {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i = 0; i < callbacks.length; i++) {
                ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPostCreated(activity,
                        savedInstanceState);
            }
        }
    }

    @UnsupportedAppUsage
        /* package */ void dispatchActivityPreStarted(@NonNull Activity activity) {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i = 0; i < callbacks.length; i++) {
                ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPreStarted(activity);
            }
        }
    }

    @UnsupportedAppUsage
    /* package */ void dispatchActivityStarted(@NonNull Activity activity) {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i=0; i<callbacks.length; i++) {
                ((ActivityLifecycleCallbacks)callbacks[i]).onActivityStarted(activity);
            }
        }
    }

    @UnsupportedAppUsage
        /* package */ void dispatchActivityPostStarted(@NonNull Activity activity) {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i = 0; i < callbacks.length; i++) {
                ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPostStarted(activity);
            }
        }
    }

    @UnsupportedAppUsage
        /* package */ void dispatchActivityPreResumed(@NonNull Activity activity) {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i = 0; i < callbacks.length; i++) {
                ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPreResumed(activity);
            }
        }
    }

    @UnsupportedAppUsage
    /* package */ void dispatchActivityResumed(@NonNull Activity activity) {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i=0; i<callbacks.length; i++) {
                ((ActivityLifecycleCallbacks)callbacks[i]).onActivityResumed(activity);
            }
        }
    }

    @UnsupportedAppUsage
        /* package */ void dispatchActivityPostResumed(@NonNull Activity activity) {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i = 0; i < callbacks.length; i++) {
                ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPostResumed(activity);
            }
        }
    }

    @UnsupportedAppUsage
        /* package */ void dispatchActivityPrePaused(@NonNull Activity activity) {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i = 0; i < callbacks.length; i++) {
                ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPrePaused(activity);
            }
        }
    }

    @UnsupportedAppUsage
    /* package */ void dispatchActivityPaused(@NonNull Activity activity) {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i=0; i<callbacks.length; i++) {
                ((ActivityLifecycleCallbacks)callbacks[i]).onActivityPaused(activity);
            }
        }
    }

    @UnsupportedAppUsage
        /* package */ void dispatchActivityPostPaused(@NonNull Activity activity) {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i = 0; i < callbacks.length; i++) {
                ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPostPaused(activity);
            }
        }
    }

    @UnsupportedAppUsage
        /* package */ void dispatchActivityPreStopped(@NonNull Activity activity) {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i = 0; i < callbacks.length; i++) {
                ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPreStopped(activity);
            }
        }
    }

    @UnsupportedAppUsage
    /* package */ void dispatchActivityStopped(@NonNull Activity activity) {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i=0; i<callbacks.length; i++) {
                ((ActivityLifecycleCallbacks)callbacks[i]).onActivityStopped(activity);
            }
        }
    }

    @UnsupportedAppUsage
        /* package */ void dispatchActivityPostStopped(@NonNull Activity activity) {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i = 0; i < callbacks.length; i++) {
                ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPostStopped(activity);
            }
        }
    }

    @UnsupportedAppUsage
        /* package */ void dispatchActivityPreSaveInstanceState(@NonNull Activity activity,
            @NonNull Bundle outState) {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i = 0; i < callbacks.length; i++) {
                ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPreSaveInstanceState(
                        activity, outState);
            }
        }
    }

    @UnsupportedAppUsage
    /* package */ void dispatchActivitySaveInstanceState(@NonNull Activity activity,
            @NonNull Bundle outState) {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i=0; i<callbacks.length; i++) {
                ((ActivityLifecycleCallbacks)callbacks[i]).onActivitySaveInstanceState(activity,
                        outState);
            }
        }
    }

    @UnsupportedAppUsage
        /* package */ void dispatchActivityPostSaveInstanceState(@NonNull Activity activity,
            @NonNull Bundle outState) {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i = 0; i < callbacks.length; i++) {
                ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPostSaveInstanceState(
                        activity, outState);
            }
        }
    }

    @UnsupportedAppUsage
        /* package */ void dispatchActivityPreDestroyed(@NonNull Activity activity) {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i = 0; i < callbacks.length; i++) {
                ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPreDestroyed(activity);
            }
        }
    }

    @UnsupportedAppUsage
    /* package */ void dispatchActivityDestroyed(@NonNull Activity activity) {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i=0; i<callbacks.length; i++) {
                ((ActivityLifecycleCallbacks)callbacks[i]).onActivityDestroyed(activity);
            }
        }
    }

    @UnsupportedAppUsage
        /* package */ void dispatchActivityPostDestroyed(@NonNull Activity activity) {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i = 0; i < callbacks.length; i++) {
                ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPostDestroyed(activity);
            }
        }
    }

    private Object[] collectComponentCallbacks() {
        Object[] callbacks = null;
        synchronized (mComponentCallbacks) {
            if (mComponentCallbacks.size() > 0) {
                callbacks = mComponentCallbacks.toArray();
            }
        }
        return callbacks;
    }

    @UnsupportedAppUsage
    private Object[] collectActivityLifecycleCallbacks() {
        Object[] callbacks = null;
        synchronized (mActivityLifecycleCallbacks) {
            if (mActivityLifecycleCallbacks.size() > 0) {
                callbacks = mActivityLifecycleCallbacks.toArray();
            }
        }
        return callbacks;
    }

    /* package */ void dispatchOnProvideAssistData(Activity activity, Bundle data) {
        Object[] callbacks;
        synchronized (this) {
            if (mAssistCallbacks == null) {
                return;
            }
            callbacks = mAssistCallbacks.toArray();
        }
        if (callbacks != null) {
            for (int i=0; i<callbacks.length; i++) {
                ((OnProvideAssistDataListener)callbacks[i]).onProvideAssistData(activity, data);
            }
        }
    }

    /** @hide */
    @Override
    public AutofillManager.AutofillClient getAutofillClient() {
        final AutofillManager.AutofillClient client = super.getAutofillClient();
        if (client != null) {
            return client;
        }
        if (android.view.autofill.Helper.sVerbose) {
            Log.v(TAG, "getAutofillClient(): null on super, trying to find activity thread");
        }
        // Okay, ppl use the application context when they should not. This breaks
        // autofill among other things. We pick the focused activity since autofill
        // interacts only with the currently focused activity and we need the fill
        // client only if a call comes from the focused activity. Sigh...
        final ActivityThread activityThread = ActivityThread.currentActivityThread();
        if (activityThread == null) {
            return null;
        }
        final int activityCount = activityThread.mActivities.size();
        for (int i = 0; i < activityCount; i++) {
            final ActivityThread.ActivityClientRecord record =
                    activityThread.mActivities.valueAt(i);
            if (record == null) {
                continue;
            }
            final Activity activity = record.activity;
            if (activity == null) {
                continue;
            }
            if (activity.getWindow().getDecorView().hasFocus()) {
                if (android.view.autofill.Helper.sVerbose) {
                    Log.v(TAG, "getAutofillClient(): found activity for " + this + ": " + activity);
                }
                return activity;
            }
        }
        if (android.view.autofill.Helper.sVerbose) {
            Log.v(TAG, "getAutofillClient(): none of the " + activityCount + " activities on "
                    + this + " have focus");
        }
        return null;
    }
}

Tips:

程序启动时,系统会自动创建 Application 对象,然后运行 onCreate() 方法,其中 android.app.Application.onCreate() 方法体为空,可以在 onCreate() 中做一些初始化工作。Application 不能自己创建,就如同不能自己创建 Activity 一样,如果我们通过 new 创建一个 Application,会得到一个普通的类的实例,如果需要应用 Application 的地方用的是我们 new 出来的实例,则会出现空指针异常。综上所述,使用 Application 一定要使用程序自己创建的 Application,在 onCreate() 中将对象赋值给一个变量(mMyApplication = this),后面开发中使用这个变量即可。

在 Android 应用中,Application 的生命周期是和整个应用一致的,只要应用没有被系统回收,这个 Application 对象就会一直存在。但是这个 Application 对象并不是始终在内存中的,它有可能会由于系统内存不足而被回收。但系统在你重新打开这个应用时并不是重新启动这个 Application 对象,它会创建一个新的 Application 对象并且启动上次用户离开时的 Activity,造成这个 app 从来没有被 kill 掉的假象。这样,之前在 Application 中缓存的数据都会重新初始化。不仅 Application 对象是这样,其它的单例或者公有静态类也有可能会由于系统内存而被杀掉。

参考:
Android系统原代码情景分析(第三版)第五章8.2节:启动Binder线程池
Android系统原代码情景分析(第三版)第12章:安卓应用程序进程的启动过程
Android Application 启动流程源码分析
Android:全面解析 熟悉而陌生 的Application类使用

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,817评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,329评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,354评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,498评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,600评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,829评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,979评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,722评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,189评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,519评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,654评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,940评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,762评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,993评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,382评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,543评论 2 349