前面两篇文章介绍了ART的启动过程,而在启动之后,我们感兴趣的就是ART是怎么运行的。回顾一下虚拟机系列的前面几篇文章,我们可以理一下思路:
一,apk以进程的形式运行,进程的创建是由zygote。
参考文章《深入理解Dalvik虚拟机- Android应用进程启动过程分析》
二,进程运行起来之后,初始化JavaVM
三,JavaVM创建之后,我们就有了JNINativeInterface,里面包含了所有的Java接口,比如FindClass,NewObject,CallObjectMethod等
四,Java的运行时的功能简单来说分为:类的加载和函数Method的执行
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<std::vector<const DexFile*>> 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<1> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
hs.NewHandle(soa.Decode<mirror::ClassLoader*>(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<jclass>(result);
}
}
}
VLOG(class_linker) <<