JavaVMExt实例化的时候function = &gJniInvokeInterface 自动注册了很多函数

这个主要是提供虚拟机接口

struct JNIInvokeInterface {
    void*       reserved0;
    void*       reserved1;
    void*       reserved2;

    jint        (*DestroyJavaVM)(JavaVM*);
    jint        (*AttachCurrentThread)(JavaVM*, JNIEnv**, void*);
    jint        (*DetachCurrentThread)(JavaVM*);
    jint        (*GetEnv)(JavaVM*, void**, jint);
    jint        (*AttachCurrentThreadAsDaemon)(JavaVM*, JNIEnv**, void*);
};

typedef _JavaVM JavaVM;

struct _JavaVM {
    const struct JNIInvokeInterface* functions;  ////JNI接口

    jint DestroyJavaVM()
    { return functions->DestroyJavaVM(this); }
    jint AttachCurrentThread(JNIEnv** p_env, void* thr_args)
    { return functions->AttachCurrentThread(this, p_env, thr_args); }
    jint DetachCurrentThread()
    { return functions->DetachCurrentThread(this); }
    jint GetEnv(void** env, jint version)
    { return functions->GetEnv(this, env, version); }
    jint AttachCurrentThreadAsDaemon(JNIEnv** p_env, void* thr_args)
    { return functions->AttachCurrentThreadAsDaemon(this, p_env, thr_args); }
};

class JavaVMExt : public JavaVM {
 public:
  JavaVMExt(Runtime* runtime, ParsedOptions* options);
  ~JavaVMExt();

  /**
   * Loads the given shared library. 'path' is an absolute pathname.
   *
   * Returns 'true' on success. On failure, sets 'detail' to a
   * human-readable description of the error.
   */
  bool LoadNativeLibrary(const std::string& path, Handle<mirror::ClassLoader> class_loader,
                         std::string* detail)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  /**
   * Returns a pointer to the code for the native method 'm', found
   * using dlsym(3) on every native library that's been loaded so far.
   */
  void* FindCodeForNativeMethod(mirror::ArtMethod* m)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  void DumpForSigQuit(std::ostream& os);

  void DumpReferenceTables(std::ostream& os)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  void SetCheckJniEnabled(bool enabled);

  void VisitRoots(RootCallback* callback, void* arg)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  void DisallowNewWeakGlobals() EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_);
  void AllowNewWeakGlobals() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
  jweak AddWeakGlobalReference(Thread* self, mirror::Object* obj)
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
  void DeleteWeakGlobalRef(Thread* self, jweak obj)
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
  void SweepJniWeakGlobals(IsMarkedCallback* callback, void* arg)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
  mirror::Object* DecodeWeakGlobal(Thread* self, IndirectRef ref)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  Runtime* runtime;  /////

  // Used for testing. By default, we'll LOG(FATAL) the reason.
  void (*check_jni_abort_hook)(void* data, const std::string& reason);
  void* check_jni_abort_hook_data;

  // Extra checking.
  bool check_jni;    ///
  bool force_copy;

  // Extra diagnostics.
  std::string trace;

  // JNI global references.
  ReaderWriterMutex globals_lock DEFAULT_MUTEX_ACQUIRED_AFTER;
  // Not guarded by globals_lock since we sometimes use SynchronizedGet in Thread::DecodeJObject.
  IndirectReferenceTable globals;

  Mutex libraries_lock DEFAULT_MUTEX_ACQUIRED_AFTER;
  Libraries* libraries GUARDED_BY(libraries_lock);

  // Used by -Xcheck:jni.
  const JNIInvokeInterface* unchecked_functions;  ////

 private:
  // TODO: Make the other members of this class also private.
  // JNI weak global references.
  Mutex weak_globals_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
  // Since weak_globals_ contain weak roots, be careful not to
  // directly access the object references in it. Use Get() with the
  // read barrier enabled.
  IndirectReferenceTable weak_globals_ GUARDED_BY(weak_globals_lock_);
  bool allow_new_weak_globals_ GUARDED_BY(weak_globals_lock_);
  ConditionVariable weak_globals_add_condition_ GUARDED_BY(weak_globals_lock_);
};
JavaVMExt::JavaVMExt(Runtime* runtime, ParsedOptions* options)
    : runtime(runtime),
      check_jni_abort_hook(nullptr),
      check_jni_abort_hook_data(nullptr),
      check_jni(false),
      force_copy(false),  // TODO: add a way to enable this
      trace(options->jni_trace_),
      globals_lock("JNI global reference table lock"),
      globals(gGlobalsInitial, gGlobalsMax, kGlobal),
      libraries_lock("JNI shared libraries map lock", kLoadLibraryLock),
      libraries(new Libraries),
      weak_globals_lock_("JNI weak global reference table lock"),
      weak_globals_(kWeakGlobalsInitial, kWeakGlobalsMax, kWeakGlobal),
      allow_new_weak_globals_(true),
      weak_globals_add_condition_("weak globals add condition", weak_globals_lock_) {
  functions = unchecked_functions = &gJniInvokeInterface; ////JNI静态函数
}

有了这个Dalvik虚拟机函数表之后,我们就可以将当前线程Attach或者Detach到Dalvik虚拟机中去,或者销毁当前进程的Dalvik虚拟机等。
        每一个Dalvik虚拟机实例还有一个JNI环境列表,保存在对应的JavaVMExt对象的成员变量envList中。注意,JavaVMExt对象的成员变量envList描述的是一个JNIEnvExt列表,其中,每一个Attach到Dalvik虚拟机中去的线程都有一个对应的JNIEnvExt,用来描述它的JNI环境。有了这个JNI环境之后,我们才可以在Java函数和C/C++函数之间互相调用。

        每一个JNIEnvExt对象都有两个成员变量prev和next,它们均是一个JNIEnvExt指针,分别指向前一个JNIEnvExt对象和后一个JNIEnvExt对象,也就是说,每一个Dalvik虚拟机实例的成员变量envList描述的是一个双向JNIEnvExt列表,其中,列表中的第一个JNIEnvExt对象描述的是主线程的JNI环境。

--------------------------------------------------------------------------------------------------------

 JNIEnvExt线程相关的JNI环境,初始化的时候就注册了很多函数functions = &gJniNativeInterface;

这个主要是提供线程JNI环境接口

struct JNINativeInterface {
    void*       reserved0;
    void*       reserved1;
    void*       reserved2;
    void*       reserved3;

    jint        (*GetVersion)(JNIEnv *);
    jclass      (*DefineClass)(JNIEnv*, const char*, jobject, const jbyte*,jsize);
    jclass      (*FindClass)(JNIEnv*, const char*);
    jmethodID   (*FromReflectedMethod)(JNIEnv*, jobject);
    jfieldID    (*FromReflectedField)(JNIEnv*, jobject);
    /* spec doesn't show jboolean parameter */
    jobject     (*ToReflectedMethod)(JNIEnv*, jclass, jmethodID, jboolean);
    jclass      (*GetSuperclass)(JNIEnv*, jclass);
    jboolean    (*IsAssignableFrom)(JNIEnv*, jclass, jclass);
    /* spec doesn't show jboolean parameter */
    jobject     (*ToReflectedField)(JNIEnv*, jclass, jfieldID, jboolean);
    jint        (*Throw)(JNIEnv*, jthrowable);
    void        (*CallStaticVoidMethod)(JNIEnv*, jclass, jmethodID, ...);
    void        (*CallStaticVoidMethodV)(JNIEnv*, jclass, jmethodID, va_list);
    void        (*CallStaticVoidMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
    jfieldID    (*GetStaticFieldID)(JNIEnv*, jclass, const char*, const char*);    
    ......................
}

typedef _JNIEnv JNIEnv;

struct _JNIEnv {
    /* do not rename this; it does not seem to be entirely opaque */
    const struct JNINativeInterface* functions;  //////

    jint GetVersion()
    { return functions->GetVersion(this); }

    jclass DefineClass(const char *name, jobject loader, const jbyte* buf,
        jsize bufLen)
    { return functions->DefineClass(this, name, loader, buf, bufLen); }

    jclass FindClass(const char* name)
    { return functions->FindClass(this, name); }

    jmethodID FromReflectedMethod(jobject method)
    { return functions->FromReflectedMethod(this, method); }

    jfieldID FromReflectedField(jobject field)
    { return functions->FromReflectedField(this, field); }

    jobject ToReflectedMethod(jclass cls, jmethodID methodID, jboolean isStatic)
    { return functions->ToReflectedMethod(this, cls, methodID, isStatic); }

    jclass GetSuperclass(jclass clazz)
    { return functions->GetSuperclass(this, clazz); }
    ........................
}

struct JNIEnvExt : public JNIEnv {
  JNIEnvExt(Thread* self, JavaVMExt* vm);    ///
  ~JNIEnvExt();

  jobject NewLocalRef(mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
  void DeleteLocalRef(jobject obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  Thread* const self;    ///
  JavaVMExt* vm;         ///

  // Frequently-accessed fields cached from JavaVM.
  bool check_jni;

  // How many nested "critical" JNI calls are we in?
  int critical;

  // Entered JNI monitors, for bulk exit on thread detach.
  ReferenceTable monitors;

  // Used by -Xcheck:jni.
  const JNINativeInterface* unchecked_functions;
};
JNIEnvExt::JNIEnvExt(Thread* self, JavaVMExt* vm)
    : self(self),
      vm(vm),
      local_ref_cookie(IRT_FIRST_SEGMENT),
      locals(kLocalsInitial, kLocalsMax, kLocal),
      check_jni(false),
      critical(0),
      monitors("monitors", kMonitorsInitial, kMonitorsMax) {
  functions = unchecked_functions = &gJniNativeInterface;  //JNI静态函数
}

 gJniNativeInterface是一个结构体,里面存放的指针一一对应classJNI中的方法,一一对应_JNIEnv中的方法

也就是说JNIEnvExt中的方法是JNI最基础的方法,由class JNI中的方法去一一实现

class JNI {
 public:
  static jint GetVersion(JNIEnv*) {
    return JNI_VERSION_1_6;
  }

  static jclass DefineClass(JNIEnv*, const char*, jobject, const jbyte*, jsize) {
    LOG(WARNING) << "JNI DefineClass is not supported";
    return nullptr;
  }

  static jclass FindClass(JNIEnv* env, const char* name) {
    CHECK_NON_NULL_ARGUMENT(name);
    Runtime* runtime = Runtime::Current();
    ClassLinker* class_linker = runtime->GetClassLinker();
    std::string descriptor(NormalizeJniClassDescriptor(name));
    ScopedObjectAccess soa(env);
    mirror::Class* c = nullptr;
    if (runtime->IsStarted()) {
      StackHandleScope<1> hs(soa.Self());
      Handle<mirror::ClassLoader> class_loader(hs.NewHandle(GetClassLoader(soa)));
      c = class_linker->FindClass(soa.Self(), descriptor.c_str(), class_loader);
    } else {
      c = class_linker->FindSystemClass(soa.Self(), descriptor.c_str());
    }
    return soa.AddLocalReference<jclass>(c);
  }

  static jmethodID FromReflectedMethod(JNIEnv* env, jobject jlr_method) {
    CHECK_NON_NULL_ARGUMENT(jlr_method);
    ScopedObjectAccess soa(env);
    return soa.EncodeMethod(mirror::ArtMethod::FromReflectedMethod(soa, jlr_method));
  }

  ......
}



const JNINativeInterface gJniNativeInterface = {
  nullptr,  // reserved0.
  nullptr,  // reserved1.
  nullptr,  // reserved2.
  nullptr,  // reserved3.
  JNI::GetVersion,
  JNI::DefineClass,
  JNI::FindClass,
  JNI::FromReflectedMethod,
  JNI::FromReflectedField,
  JNI::ToReflectedMethod,
  JNI::GetSuperclass,
  JNI::IsAssignableFrom,
  JNI::ToReflectedField,
  JNI::Throw,
  JNI::ThrowNew,
  JNI::ExceptionOccurred,
  JNI::ExceptionDescribe,
  JNI::ExceptionClear,
  JNI::FatalError,
  JNI::PushLocalFrame,
  JNI::PopLocalFrame,
  JNI::NewGlobalRef,
  JNI::DeleteGlobalRef,
  JNI::DeleteLocalRef,
  JNI::IsSameObject,
  JNI::NewLocalRef,
   ................
  JNI::CallStaticVoidMethod,
  JNI::CallStaticVoidMethodV,
  JNI::CallStaticVoidMethodA,
  JNI::GetStaticFieldID,
  JNI::GetStaticObjectField,
  JNI::GetStaticBooleanField,
  JNI::GetStaticByteField,
  JNI::GetStaticCharField,
  JNI::GetStaticShortField,
  JNI::GetStaticIntField,
  JNI::GetStaticLongField,
  JNI::GetStaticFloatField,
  JNI::GetStaticDoubleField,
  JNI::SetStaticObjectField,
  .............
};

-----------------------------------------------------------------------------------------------

startReg来注册一些Android基础核心类的JNI方法

art-code\frameworks\base\core\jni\AndroidRuntime.cpp
#define REG_JNI(name)      { name }
struct RegJNIRec {
    int (*mProc)(JNIEnv*);
};

static const RegJNIRec gRegJNI[] = {
    REG_JNI(register_com_android_internal_os_RuntimeInit),
    REG_JNI(register_android_os_SystemClock),
    REG_JNI(register_android_util_EventLog),
    REG_JNI(register_android_util_Log),
    ..........

    REG_JNI(register_android_animation_PropertyValuesHolder),
    REG_JNI(register_com_android_internal_content_NativeLibraryHelper),
    REG_JNI(register_com_android_internal_net_NetworkStatsFactory),
    REG_JNI(register_com_android_internal_app_ActivityTrigger),
};

    
int AndroidRuntime::startReg(JNIEnv* env)
{
    /*
     * This hook causes all future threads created in this process to be
     * attached to the JavaVM.  (This needs to go away in favor of JNI
     * Attach calls.)
     */
    androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);

    ALOGV("--- registering native functions ---\n");

    /*
     * Every "register" function calls one or more things that return
     * a local reference (e.g. FindClass).  Because we haven't really
     * started the VM yet, they're all getting stored in the base frame
     * and never released.  Use Push/Pop to manage the storage.
     */
    env->PushLocalFrame(200);

    //对gRegJNI中的函数遍历调用来给不同的类分别注册JNI方法
    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
        env->PopLocalFrame(NULL);
        return -1;
    }
    env->PopLocalFrame(NULL);

    //createJavaThread("fubar", quickTest, (void*) "hello");

    return 0;
}

static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
{
    for (size_t i = 0; i < count; i++) {
        if (array[i].mProc(env) < 0) {
            return -1;
        }
    }
    return 0;
}

//以此两函数注册为例
    REG_JNI(register_com_android_internal_os_RuntimeInit),
    REG_JNI(register_android_os_SystemClock),
    
static JNINativeMethod gMethods[] = {
    { "nativeFinishInit", "()V",
        (void*) com_android_internal_os_RuntimeInit_nativeFinishInit },
    { "nativeZygoteInit", "()V",
        (void*) com_android_internal_os_RuntimeInit_nativeZygoteInit },
    { "nativeSetExitWithoutCleanup", "(Z)V",
        (void*) com_android_internal_os_RuntimeInit_nativeSetExitWithoutCleanup },
};

int register_com_android_internal_os_RuntimeInit(JNIEnv* env)
{
    return jniRegisterNativeMethods(env, "com/android/internal/os/RuntimeInit",
        gMethods, NELEM(gMethods));
}

com/android/internal/os/RuntimeInit gMethods

    AndroidRuntime类的成员函数startReg首先调用函数androidSetCreateThreadFunc来设置一个线程创建钩子javaCreateThreadEtc。这个线程创建钩子是用来初始化一个Native线程的JNI环境的,也就是说,当我们在C++代码中创建一个Native线程的时候,函数javaCreateThreadEtc会被调用来初始化该Native线程的JNI环境。

     AndroidRuntime类的成员函数startReg接着调用函数register_jni_procs来注册Android核心类的JNI方法。在注册JNI方法的过程中,需要在Native代码中引用到一些Java对象,这些Java对象引用需要记录在当前线程的一个Native堆栈中。但是此时Dalvik虚拟机还没有真正运行起来,也就是当前线程的Native堆栈还没有准备就绪。在这种情况下,就需要在注册JNI方法之前,手动地将在当前线程的Native堆栈中压入一个帧(Frame),并且在注册JNI方法之后,手动地将该帧弹出来。
        当前线程的JNI环境是由参数env所指向的一个JNIEnv对象来描述的,通过调用它的成员函数PushLocalFrame和PopLocalFrame就可以手动地往当前线程的Native堆栈压入和弹出一个帧。注意,这个帧是一个本地帧,只可以用来保存Java对象在Native代码中的本地引用。

 -----------------------------------------------------------------------------------------------

最后调用java/com/android/internal/os/ZygoteInit.java的main方法

com.android.internal.os.ZygoteInit类的静态成员函数main,会进行大量的Android核心类和系统资源文件预加载。其中,预加载的Android核心类可以参考frameworks/base/preloaded-classes这个文件,而预加载的系统资源就是包含在/system/framework/framework-res.apk中。

-------------------------------------------------------------------------------------------------------

四件事情:
        1. 调用成员函数startVm来创建一个Dalvik虚拟机实例,并且保存在成员变量mJavaVM中
        2. 调用成员函数startReg来注册一些Android核心类的JNI方法。
        3. 调用参数className所描述的一个Java类的静态成员函数main,来作为Zygote进程的Java层入口。这个入口类就为com.android.internal.os.ZygoteInit。执行这一步的时候,Zygote进程中的Dalvik虚拟机实例就开始正式运作了。注意,在这一步中,也就是在com.android.internal.os.ZygoteInit类的静态成员函数main,会进行大量的Android核心类和系统资源文件预加载。其中,预加载的Android核心类可以参考frameworks/base/preloaded-classes这个文件,而预加载的系统资源就是包含在/system/framework/framework-res.apk中。
        4. 从com.android.internal.os.ZygoteInit类的静态成员函数main返回来的时候,就说明Zygote进程准备要退出来了。在退出之前,会调用前面创建的Dalvik虚拟机实例的成员函数DetachCurrentThread和DestroyJavaVM。其中,前者用来将Zygote进程的主线程脱离前面创建的Dalvik虚拟机实例,后者是用来销毁前面创建的Dalvik虚拟机实例。

 

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    /* start the virtual machine */
    JniInvocation jni_invocation; //JniInvocation是单例类。
    jni_invocation.Init(NULL);  //加载库 使用JNI_CreateJavaVM()
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);

    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }

    ..............
    char* slashClassName = toSlashClassName(className);
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
        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 {
            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");
}