art JNI(JavaVMExt)
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)); }
这样就在zygote线程中注册了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中。
-------------------------------------------------------------------------------------------------------
AndroidRuntime类的成员函数start主要做了以下四件事情:
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); //加载libart.so库 使用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"); }

浙公网安备 33010602011771号