Android类加载流程( 三 )

art\runtime\class_linker.cc::SetupClass
SetupClass设置类的一些基本字段信息 。
void ClassLinker::SetupClass(const DexFile& dex_file,const DexFile::ClassDef& dex_class_def,Handle<mirror::Class> klass,ObjPtr<mirror::ClassLoader> class_loader) {CHECK(klass != nullptr);CHECK(klass->GetDexCache() != nullptr);CHECK_EQ(mirror::Class::kStatusNotReady, klass->GetStatus());const char* descriptor = dex_file.GetClassDescriptor(dex_class_def);CHECK(descriptor != nullptr);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_);}延申:mirror命名空间下的类是底层对Java层类的映射 , 比如:mirror::Class类就是对java.lang.Class类的映射 , SetAccessFlags就是对Class类的accessFlags字段赋值 。
art\runtime\class_linker.cc::InsertClass
InsertClass函数判断类是否在列表中:
  • 如果在列表中 , 则直接返回;
  • 如果没有 , 则添加到列表 。
mirror::Class* ClassLinker::InsertClass(const char* descriptor, ObjPtr<mirror::Class> klass, size_t hash) {if (VLOG_IS_ON(class_linker)) {ObjPtr<mirror::DexCache> dex_cache = klass->GetDexCache();std::string source;if (dex_cache != nullptr) {source += " from ";source += dex_cache->GetLocation()->ToModifiedUtf8();}LOG(INFO) << "Loaded class " << descriptor << source;}{WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);ObjPtr<mirror::ClassLoader> const class_loader = klass->GetClassLoader();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);if (class_loader != nullptr) {// This is necessary because we need to have the card dirtied for remembered sets.Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(class_loader);}if (log_new_roots_) {new_class_roots_.push_back(GcRoot<mirror::Class>(klass));}}if (kIsDebugBuild) {// Test that copied methods correctly can find their holder.for (ArtMethod& method : klass->GetCopiedMethods(image_pointer_size_)) {CHECK_EQ(GetHoldingClassOfCopiedMethod(&method), klass);}}return nullptr;}
【Android类加载流程】art\runtime\class_linker.cc::LoadClass
LoadClass函数获取了dex文件中的classData部分 , 然后去调用LoadClassMembers
void ClassLinker::LoadClass(Thread* self,const DexFile& dex_file,const DexFile::ClassDef& dex_class_def,Handle<mirror::Class> klass) {const uint8_t* class_data = https://www.huyubaike.com/biancheng/dex_file.GetClassData(dex_class_def);if (class_data == nullptr) {return;// no fields or methods - for example a marker interface}LoadClassMembers(self, dex_file, class_data, klass);}
art\runtime\class_linker.cc::LoadClassMembers
LoadClassMembers函数主要逻辑是遍历类中的所有字段和函数 , 然后分别调用LoadField , LoadMethod和LinkCode
void ClassLinker::LoadClassMembers(Thread* self,const DexFile& dex_file,const uint8_t* class_data,Handle<mirror::Class> klass){......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();DCHECK_GE(field_idx, last_field_idx);// Ordering enforced by DexFileVerifier.if (num_sfields == 0 || LIKELY(field_idx > last_field_idx)) {DCHECK_LT(num_sfields, it.NumStaticFields());LoadField(it, klass, &sfields->At(num_sfields));++num_sfields;last_field_idx = field_idx;}}// Load instance fields.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);// Ordering enforced by DexFileVerifier.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;}}......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) {// duplicate casemethod->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++;}......}

经验总结扩展阅读