不知读者在平时的 Android 或 Java 开发中,对于 Class 如何加载至虚拟机中并执行,存在过多多少少的好奇吗?
或许你和笔者一样,读过好几本有关 JVM 的书籍,又或看过好几篇讲解 Class 加载的博文,但总感觉脱离源码的理论学习未免太过晦涩难懂。
故本文就从 Android Native 源码的角度,简略阅读分析下 Class 加载的部分关键流程代码实现,希望读者和我都能够从此次分析中有所收获。
双亲委派模型 首先,讲 Class 的加载,避免不了双亲委派模型,其实很好理解,就是将 Class 的加载优先代理给父级 Class Loader 进行处理,实现在 Java 层,直接看代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { Class<?> c = findLoadedClass(name); if (c == null ) { try { if (parent != null ) { c = parent.loadClass(name, false ); } else { c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { } if (c == null ) { c = findClass(name); } } return c; }
Class 加载的 Native 层入口 Native 层的类加载是从 Class.forname 方法开始的,实现在 art/runtime/native/java_lang_Class.cc 文件中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 static jclass Class_classForName (JNIEnv* env, jclass, jstring javaName, jboolean initialize, jobject javaLoader) { ... Handle<mirror::Class> c( hs.NewHandle(class_linker->FindClass(soa.Self(), descriptor.c_str(), class_loader))); if (c == nullptr ) { ... if (cnfe != nullptr ) { env->Throw(cnfe); } return nullptr ; } if (initialize) { class_linker->EnsureInitialized(soa.Self(), c, true , true ); } return soa.AddLocalReference<jclass>(c.Get()); }
ClassLinker::FindClass 的实现有以下流程
类名是单个字符,查找基本类型的 Class
从已加载的 Class Table 中查找,确保 Class 已经 Resolve 后直接返回
Class Loader 为空,则从 boot_class_path_ 中查找类
如果是数组,则运行时创建数组 Class;非数组,则从 BaseDexClassLoader 中查找
插入到 Class Loader 的 Class Table 记录中
基本类型的 Class 寻找 1 2 3 4 5 6 7 8 9 mirror::Class* ClassLinker::CreatePrimitiveClass(Thread* self, Primitive::Type type) { ObjPtr<mirror::Class> klass = AllocClass(self, mirror::Class::PrimitiveClassSize(image_pointer_size_)); if (UNLIKELY(klass == nullptr )) { self->AssertPendingOOMException(); return nullptr ; } return InitializePrimitiveClass(klass, type); }
在堆上开辟内存
kMovingClasses 定义在 art/runtime/globals.h:100 常量中,当不支持 Mark-Compact GC 时,恒为 true
初始化 Class 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 mirror::Class* ClassLinker::InitializePrimitiveClass(ObjPtr<mirror::Class> primitive_class, Primitive::Type type) { ... Handle<mirror::Class> h_class(hs.NewHandle(primitive_class)); ObjectLock<mirror::Class> lock(self, h_class); h_class->SetAccessFlags(kAccPublic | kAccFinal | kAccAbstract); h_class->SetPrimitiveType(type); h_class->SetIfTable(GetClassRoot(kJavaLangObject)->GetIfTable()); mirror::Class::SetStatus(h_class, mirror::Class::kStatusInitialized, self); const char * descriptor = Primitive::Descriptor(type); ObjPtr<mirror::Class> existing = InsertClass(descriptor, h_class.Get(), ComputeModifiedUtf8Hash(descriptor)); CHECK(existing == nullptr ) << "InitPrimitiveClass(" << type << ") failed" ; return h_class.Get(); }
启动类的寻找 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 if (descriptor[0 ] != '[' && class_loader == nullptr ) { ClassPathEntry pair = FindInClassPath(descriptor, hash, boot_class_path_); if (pair.second != nullptr ) { return DefineClass(self, descriptor, hash, ScopedNullHandle<mirror::ClassLoader>(), *pair.first, *pair.second); } else { ObjPtr<mirror::Throwable> pre_allocated = Runtime::Current()->GetPreAllocatedNoClassDefFoundError(); self->SetException(pre_allocated); return nullptr ; } }
FindInClassPath 函数中,通过遍历 boot_class_path_ 寻找正确的 Class Def
1 2 3 4 5 6 for (const DexFile* dex_file : class_path) { const DexFile::ClassDef* dex_class_def = OatDexFile::FindClassDef(*dex_file, descriptor, hash); if (dex_class_def != nullptr ) { return ClassPathEntry(dex_file, dex_class_def); } }
在 DexFile 中查找 Class Def 是对 TypeLookupTable 表进行 hash 查找
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 const DexFile::ClassDef* OatFile::OatDexFile::FindClassDef(const DexFile& dex_file, const char * descriptor, size_t hash) { ... if (LIKELY((oat_dex_file != nullptr ) && (oat_dex_file->GetTypeLookupTable() != nullptr ))) { const uint32_t class_def_idx = oat_dex_file->GetTypeLookupTable()->Lookup(descriptor, hash); return (class_def_idx != DexFile::kDexNoIndex) ? &dex_file.GetClassDef(class_def_idx) : nullptr ; } ... const DexFile::TypeId* type_id = dex_file.FindTypeId(descriptor); if (type_id != nullptr ) { dex::TypeIndex type_idx = dex_file.GetIndexForTypeId(*type_id); return dex_file.FindClassDef(type_idx); } return nullptr ; }
Class Def 的结构定义中主要是 Class 文件各部分内容的地址信息
1 2 3 4 5 6 7 8 9 10 11 12 13 struct ClassDef { dex::TypeIndex class_idx_; uint16_t pad1_; uint32_t access_flags_; dex::TypeIndex superclass_idx_; uint16_t pad2_; uint32_t interfaces_off_; dex::StringIndex source_file_idx_; uint32_t annotations_off_; uint32_t class_data_off_; uint32_t static_values_off_; ... };
Class 的定义 拿到 ClassDef,接下来则是调用 ClassLinker::DefineClass,定义在 art/runtime/class_linker.cc:2693
内部 Class 判断是否为 JDK 内部 Class,若是内部 Class,则直接赋值为已完成创建的系统 Class
1 2 3 4 5 6 7 8 9 10 11 12 13 if (strcmp (descriptor, "Ljava/lang/Object;" ) == 0 ) { klass.Assign(GetClassRoot(kJavaLangObject)); } else if (strcmp (descriptor, "Ljava/lang/Class;" ) == 0 ) { klass.Assign(GetClassRoot(kJavaLangClass)); } else if (strcmp (descriptor, "Ljava/lang/String;" ) == 0 ) { klass.Assign(GetClassRoot(kJavaLangString)); } else if (strcmp (descriptor, "Ljava/lang/ref/Reference;" ) == 0 ) { klass.Assign(GetClassRoot(kJavaLangRefReference)); } else if (strcmp (descriptor, "Ljava/lang/DexCache;" ) == 0 ) { klass.Assign(GetClassRoot(kJavaLangDexCache)); } else if (strcmp (descriptor, "Ldalvik/system/ClassExt;" ) == 0 ) { klass.Assign(GetClassRoot(kDalvikSystemClassExt)); }
在堆中分配内存 1 klass.Assign(AllocClass(self, SizeOfClassWithoutEmbeddedTables(dex_file, dex_class_def)));
对 Class 进行 PreDefine 实现在 art/runtime/openjdkjvmti/ti_class.cc:133 中 ClassPreDefine 方法
其中,首先拷贝 DexFile 并发送全局事件给 Transformer 来进行 Hook 处理(猜测是暴露给应用层进行 Dex 预处理)
1 2 3 4 std ::unique_ptr <FixedUpDexFile> dex_file_copy(FixedUpDexFile::Create(initial_dex_file));event_handler->DispatchEvent<ArtJvmtiEvent::kClassFileLoadHookNonRetransformable>(...); event_handler->DispatchEvent<ArtJvmtiEvent::kClassFileLoadHookRetransformable>(...);
Hook 预处理后,会生成新的 DexFile 和 ClassDef
1 2 3 4 5 std ::unique_ptr <const art::DexFile> dex_file(MakeSingleDexFile(self, descriptor, initial_dex_file.GetLocation(), final_len, final_dex_data));
注册 DexFile ClassLinker::RegisterDexFile 方法实现 DexFile 的注册,此处会通过 FindDexCacheDataLocked 方法,尝试从缓存中读取,此处讨论首次无缓存的情况。首先会对 Class Loader 进行必要的初始化
1 2 3 4 5 6 7 8 9 LinearAlloc* const linear_alloc = GetOrCreateAllocatorForClassLoader(class_loader); DCHECK(linear_alloc != nullptr ); ClassTable* table; { WriterMutexLock mu (self, *Locks::classlinker_classes_lock_) ;table = InsertClassTableForClassLoader(class_loader); }
这里跟进下 Class Table 是如何加进去的
DexFile 的注册关键代码如下
1 2 3 4 5 6 7 8 9 mirror::DexCache::InitializeDexCache(self, h_dex_cache.Get(), h_location.Get(), &dex_file, linear_alloc, image_pointer_size_); RegisterDexFileLocked(dex_file, h_dex_cache.Get(), h_class_loader.Get());
注册 DexFile 其实就是将其放在全局变量 dex_caches_ 中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 for (auto it = dex_caches_.begin(); it != dex_caches_.end(); ) { DexCacheData data = *it; if (self->IsJWeakCleared(data.weak_root)) { vm->DeleteWeakGlobalRef(self, data.weak_root); it = dex_caches_.erase(it); } else { ++it; } } jweak dex_cache_jweak = vm->AddWeakGlobalRef(self, dex_cache); dex_cache->SetDexFile(&dex_file); DexCacheData data; data.weak_root = dex_cache_jweak; data.dex_file = dex_cache->GetDexFile(); data.resolved_methods = dex_cache->GetResolvedMethods(); data.class_table = ClassTableForClassLoader(class_loader); DCHECK(data.class_table != nullptr ); dex_caches_.push_back(data);
最后确保 Class Loader 相同,DexCache 中的 Class Loader 要和当前加载的 Class Loader 一致,这里直接判断 Class Table 是否相同来实现
1 2 3 4 5 6 7 8 9 10 ObjPtr<mirror::DexCache> ClassLinker::EnsureSameClassLoader( ... if (data.class_table != ClassTableForClassLoader(class_loader)) { self->ThrowNewExceptionF("Ljava/lang/InternalError;" , "Attempt to register dex file %s with multiple class loaders" , data.dex_file->GetLocation().c_str()); return nullptr ; } return dex_cache; }
至此,DexFile 注册就完成了,将 DexCache 置放在 kClass 即可
1 klass->SetDexCache(dex_cache);
配置 Class 字段 ClassLinker::SetupClass 中对 Class 的信息字段进行了配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 void ClassLinker::SetupClass(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def, Handle<mirror::Class> klass, ObjPtr<mirror::ClassLoader> class_loader) { ... klass->SetClass(GetClassRoot(kJavaLangClass)); uint32_t access_flags = dex_class_def.GetJavaAccessFlags(); CHECK_EQ(access_flags & ~kAccJavaFlagsMask, 0U ); klass->SetAccessFlags(access_flags); klass->SetClassLoader(class_loader); DCHECK_EQ(klass->GetPrimitiveType(), Primitive::kPrimNot); mirror::Class::SetStatus(klass, mirror::Class::kStatusIdx, nullptr ); klass->SetDexClassDefIndex(dex_file.GetIndexForClassDef(dex_class_def)); klass->SetDexTypeIndex(dex_class_def.class_idx_); }
添加到 Class Table ClassLinker::InsertClass 方法中将 Class 哈希插入到 Class Table 中
1 2 3 4 5 6 7 ClassTable* const class_table = InsertClassTableForClassLoader(class_loader); ObjPtr<mirror::Class> existing = class_table->Lookup(descriptor, hash); if (existing != nullptr ) { return existing.Ptr(); } VerifyObject(klass); class_table->InsertWithHash(klass, hash);
加载 Class ClassLinker::LoadClass 中对类成员进行加载
1 2 3 4 5 6 7 8 9 10 11 12 void ClassLinker::LoadClass(Thread* self, const DexFile& dex_file, const DexFile::ClassDef& dex_class_def, Handle<mirror::Class> klass) { const uint8_t * class_data = dex_file.GetClassData(dex_class_def); if (class_data == nullptr ) { return ; } LoadClassMembers(self, dex_file, class_data, klass); }
类成员加载的实现在 ClassLinker::LoadClassMembers 方法中
第一步,加载静态变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 LinearAlloc* const allocator = GetAllocatorForClassLoader(klass->GetClassLoader()); ClassDataItemIterator it (dex_file, class_data) ;LengthPrefixedArray<ArtField>* sfields = AllocArtFieldArray(self, allocator, it.NumStaticFields()); size_t num_sfields = 0 ;uint32_t last_field_idx = 0u ;for (; it.HasNextStaticField(); it.Next()) { uint32_t field_idx = it.GetMemberIndex(); ... if (num_sfields == 0 || LIKELY(field_idx > last_field_idx)) { LoadField(it, klass, &sfields->At(num_sfields)); ++num_sfields; last_field_idx = field_idx; } }
LoadFiled 为每个 Field 进行初始化,包括地址、所属 Class 以及修饰符
1 2 3 4 5 6 7 8 void ClassLinker::LoadField(const ClassDataItemIterator& it, Handle<mirror::Class> klass, ArtField* dst) { const uint32_t field_idx = it.GetMemberIndex(); dst->SetDexFieldIndex(field_idx); dst->SetDeclaringClass(klass.Get()); dst->SetAccessFlags(it.GetFieldAccessFlags()); }
注意,迭代器之所以能够按序遍历,先从 static 开始,是因为地址排序就是按如此的顺序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 inline void Next () { pos_++; if (pos_ < EndOfStaticFieldsPos()) { last_idx_ = GetMemberIndex(); ReadClassDataField(); } else if (pos_ == EndOfStaticFieldsPos() && NumInstanceFields() > 0 ) { last_idx_ = 0 ; ReadClassDataField(); } else if (pos_ < EndOfInstanceFieldsPos()) { last_idx_ = GetMemberIndex(); ReadClassDataField(); } else if (pos_ == EndOfInstanceFieldsPos() && NumDirectMethods() > 0 ) { last_idx_ = 0 ; ReadClassDataMethod(); } else if (pos_ < EndOfDirectMethodsPos()) { last_idx_ = GetMemberIndex(); ReadClassDataMethod(); } else if (pos_ == EndOfDirectMethodsPos() && NumVirtualMethods() > 0 ) { last_idx_ = 0 ; ReadClassDataMethod(); } else if (pos_ < EndOfVirtualMethodsPos()) { last_idx_ = GetMemberIndex(); ReadClassDataMethod(); } else { DCHECK(!HasNext()); } }
第二步,加载实例字段
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 LengthPrefixedArray<ArtField>* ifields = AllocArtFieldArray(self, allocator, it.NumInstanceFields()); size_t num_ifields = 0u ;last_field_idx = 0u ; for (; it.HasNextInstanceField(); it.Next()) { uint32_t field_idx = it.GetMemberIndex(); DCHECK_GE(field_idx, last_field_idx); if (num_ifields == 0 || LIKELY(field_idx > last_field_idx)) { DCHECK_LT(num_ifields, it.NumInstanceFields()); LoadField(it, klass, &ifields->At(num_ifields)); ++num_ifields; last_field_idx = field_idx; } }
LoadField 与静态字段实现一致,不赘述。
静态字段和实例字段都加载完后,为 Class 赋值
1 2 klass->SetSFieldsPtr(sfields); klass->SetIFieldsPtr(ifields);
第三步,加载方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 klass->SetMethodsPtr( AllocArtMethodArray(self, allocator, it.NumDirectMethods() + it.NumVirtualMethods()), it.NumDirectMethods(), it.NumVirtualMethods()); size_t class_def_method_index = 0 ;uint32_t last_dex_method_index = DexFile::kDexNoIndex;size_t last_class_def_method_index = 0 ;for (size_t i = 0 ; it.HasNextDirectMethod(); i++, it.Next()) { ArtMethod* method = klass->GetDirectMethodUnchecked(i, image_pointer_size_); LoadMethod(dex_file, it, klass, method); LinkCode(this , method, oat_class_ptr, class_def_method_index); uint32_t it_method_index = it.GetMemberIndex(); if (last_dex_method_index == it_method_index) { method->SetMethodIndex(last_class_def_method_index); } else { method->SetMethodIndex(class_def_method_index); last_dex_method_index = it_method_index; last_class_def_method_index = class_def_method_index; } class_def_method_index++; } for (size_t i = 0 ; it.HasNextVirtualMethod(); i++, it.Next()) { ArtMethod* method = klass->GetVirtualMethodUnchecked(i, image_pointer_size_); LoadMethod(dex_file, it, klass, method); DCHECK_EQ(class_def_method_index, it.NumDirectMethods() + i); LinkCode(this , method, oat_class_ptr, class_def_method_index); class_def_method_index++; }
接下来,看具体的 ClassLinker::LoadMethod 方法的实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 void ClassLinker::LoadMethod(const DexFile& dex_file, const ClassDataItemIterator& it, Handle<mirror::Class> klass, ArtMethod* dst) { dst->SetDexMethodIndex(dex_method_idx); dst->SetDeclaringClass(klass.Get()); dst->SetCodeItemOffset(it.GetMethodCodeItemOffset()); dst->SetDexCacheResolvedMethods(klass->GetDexCache()->GetResolvedMethods(), image_pointer_size_); uint32_t access_flags = it.GetMethodAccessFlags(); if (UNLIKELY(strcmp ("finalize" , method_name) == 0 )) { if (strcmp ("V" , dex_file.GetShorty(method_id.proto_idx_)) == 0 ) { if (klass->GetClassLoader() != nullptr ) { klass->SetFinalizable(); } else { std ::string temp; const char * klass_descriptor = klass->GetDescriptor(&temp); if (strcmp (klass_descriptor, "Ljava/lang/Object;" ) != 0 && strcmp (klass_descriptor, "Ljava/lang/Enum;" ) != 0 ) { klass->SetFinalizable(); } } } } else if (method_name[0 ] == '<' ) { bool is_init = (strcmp ("<init>" , method_name) == 0 ); bool is_clinit = !is_init && (strcmp ("<clinit>" , method_name) == 0 ); if (UNLIKELY(!is_init && !is_clinit)) { LOG(WARNING) << "Unexpected '<' at start of method name " << method_name; } else { if (UNLIKELY((access_flags & kAccConstructor) == 0 )) { LOG(WARNING) << method_name << " didn't have expected constructor access flag in class " << klass->PrettyDescriptor() << " in dex file " << dex_file.GetLocation(); access_flags |= kAccConstructor; } } } dst->SetAccessFlags(access_flags); }
LinkCode 的工作主要是对 Method 的入口地址进行赋值
1 2 3 4 5 6 7 8 void OatFile::OatMethod::LinkMethod(ArtMethod* method) const { CHECK(method != nullptr ); method->SetEntryPointFromQuickCompiledCode(GetQuickCode()); } inline const void * OatFile::OatMethod::GetQuickCode() const { return GetOatPointer<const void *>(GetCodeOffset()); }
至此,Class 的 Define 过程就结束了,可以看到主要是对 Class 对象进行内存分配和属性赋值。
数组 Class 的创建 对于数组的 Class,其数组元素是由 Class Loader 进行加载的,而本身则并不是,而是运行时创建的,具体实现在 ClassLinker::CreateArrayClass 方法中。
数组类的描述符是以 “[“ 中括号前缀的,如 “[C”、”[[[[B” 或 “[Ljava/lang/String;”
首先,通过递归 FindClass 方法获取元素的 Class
1 2 MutableHandle<mirror::Class> component_type(hs.NewHandle(FindClass(self, descriptor + 1 , class_loader)));
拿到元素的 Class 类型后,会断言其 null 或 void,之后判断当前 Class Loader 与 数组元素的 Class Loader 是否相同
1 2 3 4 5 6 7 8 if (class_loader.Get() != component_type->GetClassLoader()) { ObjPtr<mirror::Class> new_class = LookupClass(self, descriptor, hash, component_type->GetClassLoader()); if (new_class != nullptr ) { return new_class.Ptr(); } }
接下来,对于元素 Class 为内置类型的 Array,赋值为预加载的 Class,而对于用户定义的 Class 则分配内存空间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 auto new_class = hs.NewHandle<mirror::Class>(nullptr );if (UNLIKELY(!init_done_)) { if (strcmp (descriptor, "[Ljava/lang/Class;" ) == 0 ) { new_class.Assign(GetClassRoot(kClassArrayClass)); } else if (strcmp (descriptor, "[Ljava/lang/Object;" ) == 0 ) { new_class.Assign(GetClassRoot(kObjectArrayClass)); } else if (strcmp (descriptor, GetClassRootDescriptor(kJavaLangStringArrayClass)) == 0 ) { new_class.Assign(GetClassRoot(kJavaLangStringArrayClass)); } else if (strcmp (descriptor, "[C" ) == 0 ) { new_class.Assign(GetClassRoot(kCharArrayClass)); } else if (strcmp (descriptor, "[I" ) == 0 ) { new_class.Assign(GetClassRoot(kIntArrayClass)); } else if (strcmp (descriptor, "[J" ) == 0 ) { new_class.Assign(GetClassRoot(kLongArrayClass)); } } if (new_class == nullptr ) { new_class.Assign(AllocClass(self, mirror::Array::ClassSize(image_pointer_size_))); if (new_class == nullptr ) { self->AssertPendingOOMException(); return nullptr ; } new_class->SetComponentType(component_type.Get()); }
对 Class 的基本属性进行赋值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 ObjPtr<mirror::Class> java_lang_Object = GetClassRoot(kJavaLangObject); new_class->SetSuperClass(java_lang_Object); new_class->SetVTable(java_lang_Object->GetVTable()); new_class->SetPrimitiveType(Primitive::kPrimNot); new_class->SetClassLoader(component_type->GetClassLoader()); if (component_type->IsPrimitive()) { new_class->SetClassFlags(mirror::kClassFlagNoReferenceFields); } else { new_class->SetClassFlags(mirror::kClassFlagObjectArray); } mirror::Class::SetStatus(new_class, mirror::Class::kStatusLoaded, self); new_class->PopulateEmbeddedVTable(image_pointer_size_); ImTable* object_imt = java_lang_Object->GetImt(image_pointer_size_); new_class->SetImt(object_imt, image_pointer_size_); mirror::Class::SetStatus(new_class, mirror::Class::kStatusInitialized, self); { ObjPtr<mirror::IfTable> array_iftable = array_iftable_.Read(); CHECK(array_iftable != nullptr ); new_class->SetIfTable(array_iftable); } int access_flags = new_class->GetComponentType()->GetAccessFlags();access_flags &= kAccJavaFlagsMask; access_flags |= kAccAbstract | kAccFinal; access_flags &= ~kAccInterface; new_class->SetAccessFlags(access_flags);
最后,置入 Class Table 中并返回
1 2 3 4 5 6 7 8 ObjPtr<mirror::Class> existing = InsertClass(descriptor, new_class.Get(), hash); if (existing == nullptr ) { Runtime::Current()->GetRuntimeCallbacks()->ClassLoad(new_class); Runtime::Current()->GetRuntimeCallbacks()->ClassPrepare(new_class, new_class); jit::Jit::NewTypeLoadedIfUsingJit(new_class.Get()); return new_class.Get(); }
非启动类的寻找 对于非 Boot Class Loader 的类,Class 的加载是在 ClassLinker::FindClassInBaseDexClassLoader 方法中实现的
1 2 3 FindClassInBaseDexClassLoader(soa, self, descriptor, hash, class_loader, &result_ptr); ... return result_ptr.Ptr();
首先,对 Boot Class Loader 进行判断,满足则跳转到 Boot Class 的流程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 if (IsBootClassLoader(soa, class_loader.Get())) { ClassPathEntry pair = FindInClassPath(descriptor, hash, boot_class_path_); if (pair.second != nullptr ) { ObjPtr<mirror::Class> klass = LookupClass(self, descriptor, hash, nullptr ); if (klass != nullptr ) { *result = EnsureResolved(self, descriptor, klass); } else { *result = DefineClass(self, descriptor, hash, ScopedNullHandle<mirror::ClassLoader>(), *pair.first, *pair.second); } if (*result == nullptr ) { CHECK(self->IsExceptionPending()) << descriptor; self->ClearException(); } } else { *result = nullptr ; } return true ; }
判断 Class 是否满足 PathClassLoader 或 DexClassLoader,否则为不支持的 Class Loader
1 2 3 4 5 6 7 8 9 if (soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_PathClassLoader) != class_loader->GetClass()) { if (soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_DexClassLoader) != class_loader->GetClass()) { *result = nullptr ; return false ; } }
之后,找到对应的 DexFile 地址
1 2 3 4 5 6 7 ArtField* const cookie_field = jni::DecodeArtField(WellKnownClasses::dalvik_system_DexFile_cookie); ArtField* const dex_file_field = jni::DecodeArtField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile); ObjPtr<mirror::Object> dex_path_list = jni::DecodeArtField(WellKnownClasses::dalvik_system_BaseDexClassLoader_pathList)-> GetObject(class_loader.Get());
然后从 DexFile 中拿到 Class 定义,再走 Class 定义的流程就完成 Class 的加载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 ObjPtr<mirror::Object> dex_file = dex_file_field->GetObject(element); if (dex_file != nullptr ) { ObjPtr<mirror::LongArray> long_array = cookie_field->GetObject(dex_file)->AsLongArray(); if (long_array == nullptr ) { LOG(WARNING) << "Null DexFile::mCookie for " << descriptor; break ; } int32_t long_array_size = long_array->GetLength(); for (int32_t j = kDexFileIndexStart; j < long_array_size; ++j) { const DexFile* cp_dex_file = reinterpret_cast <const DexFile*>(static_cast <uintptr_t >( long_array->GetWithoutChecks(j))); const DexFile::ClassDef* dex_class_def = OatDexFile::FindClassDef(*cp_dex_file, descriptor, hash); if (dex_class_def != nullptr ) { ObjPtr<mirror::Class> klass = DefineClass(self, descriptor, hash, class_loader, *cp_dex_file, *dex_class_def); if (klass == nullptr ) { CHECK(self->IsExceptionPending()) << descriptor; self->ClearException(); return true ; } *result = klass; return true ; } }
更新 Class Table Class 寻找的最后一步,就是将已实例化的 Class 对象置入到 Class Table 中
1 2 3 4 5 6 7 8 9 ClassTable* const class_table = InsertClassTableForClassLoader(class_loader.Get()); old = class_table->Lookup(descriptor, hash); if (old == nullptr ) { old = result_ptr; if (descriptor_equals) { class_table->InsertWithHash(result_ptr.Ptr(), hash); Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(class_loader.Get()); } }
Class Table 是 Native 层存放 Class 的集合类,在 Java 层表现为 Class Loader 中的 classTable 地址指针
获取 Class Table 的逻辑实现在 ClassLinker::InsertClassTableForClassLoader 方法中
1 2 3 4 5 6 7 8 9 10 11 12 ClassTable* ClassLinker::InsertClassTableForClassLoader(ObjPtr<mirror::ClassLoader> class_loader) { if (class_loader == nullptr ) { return &boot_class_table_; } ClassTable* class_table = class_loader->GetClassTable(); if (class_table == nullptr ) { RegisterClassLoader(class_loader); class_table = class_loader->GetClassTable(); DCHECK(class_table != nullptr ); } return class_table; }
总结 回顾本文,跟进了基本类型 Class、数组类 Class、一般类 Class 查找和定义过程的 Native 层实现,能够让读者对 Android 中 Class 的加载过程有进一步的理解。而此时,本文对 Class 加载的分析就基本结束了,但对于理解完整的 Class 加载过程,文中提及的仅仅是冰山一角,还需要我们多钻研多学习。