深入理解ART虚拟机—ART的函数运行机制
前面两篇文章介绍了ART的启动过程,而在启动之后,我们感兴趣的就是ART是怎么运行的。回顾一下虚拟机系列的前面几篇文章,我们可以理一下思路:
一,apk以进程的形式运行,进程的创建是由zygote。
参考文章《深入理解Dalvik虚拟机- Android应用进程启动过程分析》
二,进程运行起来之后,初始化JavaVM
参考文章《深入理解ART虚拟机—虚拟机的启动》
三,JavaVM创建之后,我们就有了JNINativeInterface,里面包含了所有的Java接口,比如FindClass,NewObject,CallObjectMethod等
参考文章《深入理解ART虚拟机—虚拟机的启动》
四,Java的运行时的功能简单来说分为:类的加载和函数Method的执行
参考文章《深入理解Dalvik虚拟机- 解释器的运行机制》
art的JNINativeInterface的定义如下:
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::EnsureLocalCapacity,JNI::AllocObject,JNI::NewObject,JNI::NewObjectV,JNI::NewObjectA,JNI::GetObjectClass,JNI::IsInstanceOf,JNI::GetMethodID,JNI::CallObjectMethod,JNI::CallObjectMethodV,JNI::CallObjectMethodA,JNI::CallBooleanMethod,JNI::CallBooleanMethodV,JNI::CallBooleanMethodA,JNI::CallByteMethod,JNI::CallByteMethodV,JNI::CallByteMethodA,JNI::CallCharMethod,JNI::CallCharMethodV,JNI::CallCharMethodA,JNI::CallShortMethod,JNI::CallShortMethodV,JNI::CallShortMethodA,JNI::CallIntMethod,JNI::CallIntMethodV,JNI::CallIntMethodA,JNI::CallLongMethod,JNI::CallLongMethodV,JNI::CallLongMethodA,JNI::CallFloatMethod,JNI::CallFloatMethodV,JNI::CallFloatMethodA,JNI::CallDoubleMethod,JNI::CallDoubleMethodV,JNI::CallDoubleMethodA,JNI::CallVoidMethod,JNI::CallVoidMethodV,JNI::CallVoidMethodA,JNI::CallNonvirtualObjectMethod,JNI::CallNonvirtualObjectMethodV,JNI::CallNonvirtualObjectMethodA,JNI::CallNonvirtualBooleanMethod,JNI::CallNonvirtualBooleanMethodV,JNI::CallNonvirtualBooleanMethodA,JNI::CallNonvirtualByteMethod,JNI::CallNonvirtualByteMethodV,JNI::CallNonvirtualByteMethodA,JNI::CallNonvirtualCharMethod,JNI::CallNonvirtualCharMethodV,JNI::CallNonvirtualCharMethodA,JNI::CallNonvirtualShortMethod,JNI::CallNonvirtualShortMethodV,JNI::CallNonvirtualShortMethodA,JNI::CallNonvirtualIntMethod,JNI::CallNonvirtualIntMethodV,JNI::CallNonvirtualIntMethodA,JNI::CallNonvirtualLongMethod,JNI::CallNonvirtualLongMethodV,JNI::CallNonvirtualLongMethodA,JNI::CallNonvirtualFloatMethod,JNI::CallNonvirtualFloatMethodV,JNI::CallNonvirtualFloatMethodA,JNI::CallNonvirtualDoubleMethod,JNI::CallNonvirtualDoubleMethodV,JNI::CallNonvirtualDoubleMethodA,JNI::CallNonvirtualVoidMethod,JNI::CallNonvirtualVoidMethodV,JNI::CallNonvirtualVoidMethodA,JNI::GetFieldID,JNI::GetObjectField,JNI::GetBooleanField,JNI::GetByteField,JNI::GetCharField,JNI::GetShortField,JNI::GetIntField,JNI::GetLongField,JNI::GetFloatField,JNI::GetDoubleField,JNI::SetObjectField,JNI::SetBooleanField,JNI::SetByteField,JNI::SetCharField,JNI::SetShortField,JNI::SetIntField,JNI::SetLongField,JNI::SetFloatField,JNI::SetDoubleField,JNI::GetStaticMethodID,JNI::CallStaticObjectMethod,JNI::CallStaticObjectMethodV,JNI::CallStaticObjectMethodA,JNI::CallStaticBooleanMethod,JNI::CallStaticBooleanMethodV,JNI::CallStaticBooleanMethodA,JNI::CallStaticByteMethod,JNI::CallStaticByteMethodV,JNI::CallStaticByteMethodA,JNI::CallStaticCharMethod,JNI::CallStaticCharMethodV,JNI::CallStaticCharMethodA,JNI::CallStaticShortMethod,JNI::CallStaticShortMethodV,JNI::CallStaticShortMethodA,JNI::CallStaticIntMethod,JNI::CallStaticIntMethodV,JNI::CallStaticIntMethodA,JNI::CallStaticLongMethod,JNI::CallStaticLongMethodV,JNI::CallStaticLongMethodA,JNI::CallStaticFloatMethod,JNI::CallStaticFloatMethodV,JNI::CallStaticFloatMethodA,JNI::CallStaticDoubleMethod,JNI::CallStaticDoubleMethodV,JNI::CallStaticDoubleMethodA,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,JNI::SetStaticBooleanField,JNI::SetStaticByteField,JNI::SetStaticCharField,JNI::SetStaticShortField,JNI::SetStaticIntField,JNI::SetStaticLongField,JNI::SetStaticFloatField,JNI::SetStaticDoubleField,JNI::NewString,JNI::GetStringLength,JNI::GetStringChars,JNI::ReleaseStringChars,JNI::NewStringUTF,JNI::GetStringUTFLength,JNI::GetStringUTFChars,JNI::ReleaseStringUTFChars,JNI::GetArrayLength,JNI::NewObjectArray,JNI::GetObjectArrayElement,JNI::SetObjectArrayElement,JNI::NewBooleanArray,JNI::NewByteArray,JNI::NewCharArray,JNI::NewShortArray,JNI::NewIntArray,JNI::NewLongArray,JNI::NewFloatArray,JNI::NewDoubleArray,JNI::GetBooleanArrayElements,JNI::GetByteArrayElements,JNI::GetCharArrayElements,JNI::GetShortArrayElements,JNI::GetIntArrayElements,JNI::GetLongArrayElements,JNI::GetFloatArrayElements,JNI::GetDoubleArrayElements,JNI::ReleaseBooleanArrayElements,JNI::ReleaseByteArrayElements,JNI::ReleaseCharArrayElements,JNI::ReleaseShortArrayElements,JNI::ReleaseIntArrayElements,JNI::ReleaseLongArrayElements,JNI::ReleaseFloatArrayElements,JNI::ReleaseDoubleArrayElements,JNI::GetBooleanArrayRegion,JNI::GetByteArrayRegion,JNI::GetCharArrayRegion,JNI::GetShortArrayRegion,JNI::GetIntArrayRegion,JNI::GetLongArrayRegion,JNI::GetFloatArrayRegion,JNI::GetDoubleArrayRegion,JNI::SetBooleanArrayRegion,JNI::SetByteArrayRegion,JNI::SetCharArrayRegion,JNI::SetShortArrayRegion,JNI::SetIntArrayRegion,JNI::SetLongArrayRegion,JNI::SetFloatArrayRegion,JNI::SetDoubleArrayRegion,JNI::RegisterNatives,JNI::UnregisterNatives,JNI::MonitorEnter,JNI::MonitorExit,JNI::GetJavaVM,JNI::GetStringRegion,JNI::GetStringUTFRegion,JNI::GetPrimitiveArrayCritical,JNI::ReleasePrimitiveArrayCritical,JNI::GetStringCritical,JNI::ReleaseStringCritical,JNI::NewWeakGlobalRef,JNI::DeleteWeakGlobalRef,JNI::ExceptionCheck,JNI::NewDirectByteBuffer,JNI::GetDirectBufferAddress,JNI::GetDirectBufferCapacity,JNI::GetObjectRefType,
};这些函数的定义在jni_internal.cc。
我们要分析art的运行机制,就需要弄清楚类的加载和art函数的执行:
一,类的加载
dalvik的类加载我们已经在《深入理解Dalvik虚拟机- Android应用进程启动过程分析》分析了,Android应用进程启动的时候会创建BaseDexClassLoader,这个BaseDexClassLoader包含了自身apk。再回顾一下过程:
1, app_process作为zygote server通过local socket处理进程创建请求,zygote server是在ZygoteInit.main函数里调用ZygoteInit.runSelectLoop监听。
2, 接收到zygote client的fork请求之后,调用ZygoteConnection.runOnce,调用Zygote.forkAndSpecialize创建新进程
3, 进程创建之后,由ZygoteConnection.handleParentProc来初始化进程,最终会调用ActivityThread.main函数
4, ActivityThread.main -> ActivityThread.attach -> ActivityThread.bindApplication -> Activity.handleBindApplication,handleBindApplication会初始化BaseDexClassLoader。
5, 类的加载经过了ClassLoader.loadClass->BaseDexClassLoader.findClass->DexPathList.findClass->DexFile.loadClassBinaryName->DexFile.defineClassNative->DexFile_defineClassNative(runtime/native/dalvik_system_DexFile.cc)
这个初始化过程,art和dalvik都是一样的。art的DexFile_defineClassNative由ClassLinker的DefineClass来加载类。
static jclass DexFile_defineClassNative(JNIEnv* env, jclass, jstring javaName, jobject javaLoader,jobject cookie) {std::unique_ptr> dex_files = ConvertJavaArrayToNative(env, cookie);if (dex_files.get() == nullptr) {VLOG(class_linker) << "Failed to find dex_file";DCHECK(env->ExceptionCheck());return nullptr;}ScopedUtfChars class_name(env, javaName);if (class_name.c_str() == nullptr) {VLOG(class_linker) << "Failed to find class_name";return nullptr;}const std::string descriptor(DotToDescriptor(class_name.c_str()));const size_t hash(ComputeModifiedUtf8Hash(descriptor.c_str()));for (auto& dex_file : *dex_files) {const DexFile::ClassDef* dex_class_def = dex_file->FindClassDef(descriptor.c_str(), hash);if (dex_class_def != nullptr) {ScopedObjectAccess soa(env);ClassLinker* class_linker = Runtime::Current()->GetClassLinker();class_linker->RegisterDexFile(*dex_file);StackHandleScope hs(soa.Self());Handle class_loader(hs.NewHandle(soa.Decode(javaLoader)));mirror::Class* result = class_linker->DefineClass(soa.Self(), descriptor.c_str(), hash,class_loader, *dex_file, *dex_class_def);if (result != nullptr) {VLOG(class_linker) << "DexFile_defineClassNative returning " << result<< " for " << class_name.c_str();return soa.AddLocalReference(result);}}}VLOG(class_linker) <&
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
