ART:類的加載、鏈接和初始化

虛擬機調用java類的成員函數時,如果類還沒有加載,要先加載類,對這個類做一些處理,直到所有信息都準備好後,才能被使用。

  • 加載:其實就是把類信息從dex文件提取到虛擬機內部。(也可能是從jar、oat)
  • 鏈接:可以細分爲校驗、準備和解析。校驗合法性,類格式是否正確、字節碼是否合法等;Prepare指爲類信息分配一塊存儲空間;Resolve,如果類成員引用其他類的話,可能需要把其他類也加載到虛擬機。
  • 初始化:初始化靜態成員變量值,執行static語句塊等。

何時會觸發類的加載鏈接流程?

ART中處理類的加載和鏈接工作的入口函數是DefineClass,類的初始化函數則只有在創建這個類的對象或者操作這個類的成員方法或變量是纔會觸發。

DefineClass在很多地方都可能被觸發,如下:

  • FindClass:根據類的字符串名搜索一個類。如果沒有的話,可能觸發類的加載和鏈接。
  • Resolve相關函數:名字雖然叫Resolve,但不是類加載、鏈接和初始化過程中提到的Resolve,它可能觸發類的加載鏈接。ClassLinker::ResolveType、ResolveMethod、ResolveString、ResolveField。

以FindClass爲例,調用流程如下:


前言:基礎類型介紹(本篇基於android9)

ArtField和ArtMethod分別代表類的成員變量和成員方法的數據結構。

class ArtField {
  GcRoot<mirror::Class> declaring_class_;//在哪個類中被定義
  uint32_t access_flags_ = 0;//訪問標記
  uint32_t field_dex_idx_ = 0;//dex文件中field_ids數組中的索引
  uint32_t offset_ = 0;//成員變量的offset,ArtField本身並不提供變量所需空間,指向地址
};
class ArtMethod {
  GcRoot<mirror::Class> declaring_class_;
  std::atomic<std::uint32_t> access_flags_;
  uint32_t dex_code_item_offset_;
  uint32_t dex_method_index_;

  uint16_t method_index_;  //與class類管理成員函數有關
  uint16_t hotness_count_;//熱度,與JIT有關

  struct PtrSizedFields {
    void* data_;//與JNI有關
    void* entry_point_from_quick_compiled_code_;//java方法入口函數地址
  } ptr_sized_fields_;
};

Dex文件按自己的格式存儲type_ids、string_ids、field_ids和method_ids等,基本都藉助symbol reference來間接獲取信息。相反,DexCache則是直接包含最終信息。

class DexCache : public Object {
  HeapReference<String> location_;//dex文件對應的路徑
  uint64_t dex_file_;               // DexFile*,指向關聯的dex文件
  /* ArtField**指向ArtField*數組,成員類型爲ArtField*。改數組存儲了一個dex文件中定義的所有類的成    
  員變量。另外,只有那些解析後的ArtField對象纔會存到這個數組裏。該字段和dex文件裏的field_ids
  數組有關。  */
  uint64_t resolved_fields_;
  /* ArtMethod**指向ArtMethod*數組,成員類型爲ArtMethod*。改數組存儲了一個dex文件中定義的所
  有類的成員變量。另外,只有那些解析後的ArtMethod對象纔會存到這個數組裏。該字段和dex文件裏
  的method_ids數組有關。  */
  uint64_t resolved_methods_;
  /*實際爲GcRoot<Class>*,指向GcRoot<Class>數組,成員類型爲GcRoot<Class>(本質上是
  mirror::Class*)。它存儲該dex文件裏使用的數據類型信息數組。該字段和dex文件裏的type_ids數組有
  關。  */
  uint64_t resolved_types_;         // 例如:Ljava/lang/String
  /*實際爲GcRoot<String>*,指向GcRoot<String>數組,成員類型爲GcRoot<String>(本質上是
  mirror::String*)。它存儲該dex文件裏使用的字符串信息數組。該字段和dex文件裏的string_ids數組
  有關。  */
  uint64_t strings_;

  //上述四個數組的長度
  uint32_t num_resolved_fields_;
  uint32_t num_resolved_methods_;
  uint32_t num_resolved_types_;
  uint32_t num_strings_;
};

Class成員變量非常多,如下幾個尤其值得注意:
iftable_:保存該類直接實現或間接實現的接口信息。直接實現是指該類自己implements的某個接口,間接實現是指它的繼承關係樹上有某個祖父類implements了某個接口。另外,一條接口信息包含兩個部分,第一部分是接口類所對應的Class對象,第二部分則是該接口類中的方法。
vtabl_:保存了所有直接定義或間接定義的virtual方法。比如Object類中的wait、notify、toString等方法。
methods_:methods_只包含本類直接定義的direct、virtual方法和拷貝過來的諸如Miranda這樣的方法。一般vtable_包含內容遠多於methods。
embedded_vtable_:隱含成員變量。能實例化的class,vtable_=nullptr,embedded_vtable_代替;embedded_imtable_包含64個元素,只存儲virtual方法中屬於接口的方法,類似於快表。索引爲dexIndex%kImtSize取模。

direct_methods:該類中static、private、構造函數.
virtual_methods:除direct之外的,並且不包括從父類繼承的函數(沒有重載它的話).

enum class ClassStatus : uint8_t {
  kNotReady = 0,
  kRetired = 1,
  kErrorResolved = 2,
  kErrorUnresolved = 3,
  kIdx = 4,
  kLoaded = 5,
  kResolving = 6,
  kResolved = 7,
  kVerifying = 8,
  kRetryVerificationAtRuntime = 9,
  kVerifyingAtRuntime = 10,
  kVerified = 11,
  kSuperclassValidated = 12,
  kInitializing = 13,
  kInitialized = 14,
  kLast = kInitialized
};

class Class : public Object {
  HeapReference<ClassLoader> class_loader_;//加載本類的ClassLoader對象。如果爲空,則爲bootstrap system loader
  HeapReference<DexCache> dex_cache_;//該類緩存在哪個DexCache對象中。
  HeapReference<IfTable> iftable_;//interface信息表
  HeapReference<String> name_;//類名
  HeapReference<Class> super_class_;//父類
  HeapReference<PointerArray> vtable_;//虛函數表
  /* [0,virtual_methods_offset_):本類的direct函數
     [virtual_methods_offset_,copied_methods_offset_):本類的virtual函數
     [copied_methods_offset_, ...)諸如miranda函數等  */
  uint64_t methods_;
  uint16_t virtual_methods_offset_;
  uint16_t copied_methods_offset_;

  uint64_t sfields_;//本類的靜態成員變量
  uint32_t access_flags_;//訪問標誌
  uint32_t class_flags_;//虛擬機內部使用
  uint32_t class_size_;//當分配一個對象時,用於說明這個類對象所需內存大小
  int32_t dex_class_def_idx_;//本類在dex文件中class_defs數組對應的索引
  int32_t dex_type_idx_;//本類在dex文件裏type_ids中的索引
  uint32_t num_reference_instance_fields_;//引用類型的非靜態成員變量個數
  uint32_t num_reference_static_fields_;//引用類型的靜態成員變量個數
  uint32_t object_size_;//實例所佔內存大小。也就是new一個實例時所需內存大小
  uint32_t status_;//類狀態
  static GcRoot<Class> java_lang_Class_;//指向代表java/lang/Class的類對象
  
  //下面三個變量雖然在註釋語句,但實際的Class對象內存空間可能包含對應內容
  // ImTableEntry embedded_imtable_[0];
  // VTableEntry embedded_vtable_[0];
  // uint32_t fields_[0];
};

加載鏈接詳細流程:

核心功能都由DefineClass()承擔,如下按加載鏈接流程分段介紹,代碼部分進行了刪減,只保留關鍵代碼:

1.加載(load)

ClassLinker::SetupClass
首先SetupClass把類的狀態從kStatusNotReady切換爲kStatusIdx,併爲傳入的klass對象設置一些最基本信息。

void ClassLinker::SetupClass(const DexFile& dex_file,
                             const DexFile::ClassDef& dex_class_def,
                             Handle<mirror::Class> klass,
                             ObjPtr<mirror::ClassLoader> class_loader) {
  //SetClass是Class的基類mirror Object中的函數。
  //Class也是一種Object,所以此處設置它的類類型爲"java/lang/Class"對應的那個Class對象。
  klass->SetClass(GetClassRoot(kJavaLangClass));
  //設置訪問標誌及該類的加載器對象
  const char* descriptor = dex_file.GetClassDescriptor(dex_class_def);
  klass->SetAccessFlags(access_flags);
  klass->SetClassLoader(class_loader);
  //設置klass的狀態爲kIdx
  mirror::Class::SetStatus(klass, ClassStatus::kIdx, nullptr);
  //設置klass的dex_class_def_idx_和dex_type_idx_成員變量
  klass->SetDexClassDefIndex(dex_file.GetIndexForClassDef(dex_class_def));
  klass->SetDexTypeIndex(dex_class_def.class_idx_);
}

ClassLinker::LoadClass
LoadClass()首先從dex中提取class_data信息,然後調用LoadClassMembers()加載靜態、非靜態成員變量,direct、virtual函數等信息到klass。

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);
  LoadClassMembers(self, dex_file, class_data, klass);
}
void ClassLinker::LoadClassMembers(Thread* self,
                                   const DexFile& dex_file,
                                   const uint8_t* class_data,
                                   Handle<mirror::Class> klass) {
    // Load static fields.
    LinearAlloc* const allocator = GetAllocatorForClassLoader(klass->GetClassLoader());
    //創建class_data_item迭代器
    ClassDataItemIterator it(dex_file, class_data);
    //分配存儲類靜態成員變量的固定長度數組sfields
    LengthPrefixedArray<ArtField>* sfields = AllocArtFieldArray(self,
                                                                allocator,
                                                                it.NumStaticFields());
    //遍歷class_data_item中的靜態成員變量數組,然後填充到sfields
    for (; it.HasNextStaticField(); it.Next()) {
      LoadField(it, klass, &sfields->At(num_sfields));
    }
    
    // Load instance fields.
    //同理,填充非靜態成員變量
    LengthPrefixedArray<ArtField>* ifields = AllocArtFieldArray(self,
                                                                allocator,
                                                                it.NumInstanceFields());
    for (; it.HasNextInstanceField(); it.Next()) {
      LoadField(it, klass, &ifields->At(num_ifields));
    }
    
    // Load methods.
    //是否關聯有oat class,LinkCode使用,設置ArtMethod入口函數地址
    const OatFile::OatClass* oat_class_ptr = has_oat_class ? &oat_class : nullptr;
    //設置Class類的methods_成員變量,包含direct、virtual函數
    klass->SetMethodsPtr(AllocArtMethodArray(self, allocator, it.NumDirectMethods() + it.NumVirtualMethods()),
        it.NumDirectMethods(),
        it.NumVirtualMethods());
    //遍歷direct,加載它們然後關聯字節碼
    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);
      //設置method_index_,該值就是這個ArtMethod位於klass methods_數組中的位置
      uint32_t it_method_index = it.GetMemberIndex();
      method->SetMethodIndex(class_def_method_index);
    }
    //virtual方法,它們的method_index_和methods_數組沒有關係,不用調用SetMethodIndex
    for (size_t i = 0; it.HasNextVirtualMethod(); i++, it.Next()) {
      ArtMethod* method = klass->GetVirtualMethodUnchecked(i, image_pointer_size_);
      LoadMethod(dex_file, it, klass, method);
      LinkCode(this, method, oat_class_ptr, class_def_method_index);
    }
}

ClassLinker::LoadField

void ClassLinker::LoadField(const ClassDataItemIterator& it,
                            Handle<mirror::Class> klass,
                            ArtField* dst) {
  const uint32_t field_idx = it.GetMemberIndex();
  dst->SetDexFieldIndex(field_idx);//設置對應dex文件裏的field_idx
  dst->SetDeclaringClass(klass.Get());//由哪個Class對象定義

  // 9.0 hidden API標誌
  uint32_t access_flags = it.GetFieldAccessFlags();
  if (klass->IsBootStrapClassLoaded()) {
    access_flags =
        HiddenApiAccessFlags::EncodeForRuntime(access_flags, it.DecodeHiddenAccessFlags());
  }
  dst->SetAccessFlags(access_flags);//訪問標誌
}

ClassLinker::LoadMethod

void ClassLinker::LoadMethod(const DexFile& dex_file,
                             const ClassDataItemIterator& it,
                             Handle<mirror::Class> klass,
                             ArtMethod* dst) {
  uint32_t dex_method_idx = it.GetMemberIndex();
  const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx);
  const char* method_name = dex_file.StringDataByIdx(method_id.name_idx_);

  dst->SetDexMethodIndex(dex_method_idx);//設置dex_method_idx
  dst->SetDeclaringClass(klass.Get());//設置declaring_class_
  dst->SetCodeItemOffset(it.GetMethodCodeItemOffset());//設置dex_code_item_offset_
  uint32_t access_flags = it.GetMethodAccessFlags();//設置訪問標誌
  //9.0 hidden API標誌
  if (klass->IsBootStrapClassLoaded()) {
    access_flags =
        HiddenApiAccessFlags::EncodeForRuntime(access_flags, it.DecodeHiddenAccessFlags());
  }
  //如果函數名爲"finalize",設置該類爲finalizable
  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 {...}
    }
  } else if (method_name[0] == '<') {
      ......//如果函數名爲"<init>"或"<clinit>",設置訪問標誌kAccConstructor
    }
  }
  dst->SetAccessFlags(access_flags);
}

另外,如果存在基類或實現了接口類,會調用ClassLinker::LoadSuperAndInterfaces去找,主要調用ClassLinker::ResolveType去解析,內部又調用FindClass,如果類不存在,則會觸發目標類的加載和鏈接。

2.鏈接(link)

經過上述的load過程,類的基本信息已經從dex文件提取出來並轉化成了mirror Class對象,LinkCass最主要是解析和填充iftable_、vtable_等。

bool ClassLinker::LinkClass(Thread* self,
                            const char* descriptor,
                            Handle<mirror::Class> klass,
                            Handle<mirror::ObjectArray<mirror::Class>> interfaces,
                            MutableHandle<mirror::Class>* h_new_class_out) {
  //根據父類的類屬性,設置本類的一些屬性
  LinkSuperClass(klass);
  //Interface Method Table的縮寫,提供接口方法的快表查詢
  ArtMethod* imt_data[ImTable::kSize];
  //對該類包含的方法進行處理。(包括它實現的接口、繼承自父類的方法等)
  LinkMethods(self, klass, interfaces, &new_conflict, imt_data);
  //對成員變量進行處理
  LinkInstanceFields(self, klass);
  LinkStaticFields(self, klass, &class_size);
  //處理Class的reference_instance_offsets_成員變量 TODO
  CreateReferenceInstanceOffsets(klass);

  if (!klass->IsTemp() || (!init_done_ && klass->GetClassSize() == class_size)) {
    //當目標類是基礎數據類、抽象類(不包括數組)、接口類時,不需要額外操作
    //將klass狀態設置爲kResolved,然後賦值給h_new_class_out即可
    mirror::Class::SetStatus(klass, ClassStatus::kResolved, self);
    h_new_class_out->Assign(klass.Get());
  } else {
    StackHandleScope<1> hs(self);
    //CopyOf是關鍵,先創建一個大小爲class_size的Class對象,然後將信息拷貝到這個新Class中。
    auto h_new_class = hs.NewHandle(klass->CopyOf(self, class_size, imt, image_pointer_size_));
    //清理klass內容
    klass->SetMethodsPtrUnchecked(nullptr, 0, 0);
    klass->SetSFieldsPtrUnchecked(nullptr);
    klass->SetIFieldsPtrUnchecked(nullptr);
    {
      //更新ClassTable中對應的信息
      ObjPtr<mirror::Class> existing = table->UpdateClass(descriptor, h_new_class.Get(),
                                                   ComputeModifiedUtf8Hash(descriptor));
    }
    //設置klass狀態爲kRetired,表示已被廢棄
    mirror::Class::SetStatus(klass, ClassStatus::kRetired, self);
    //設置新類狀態爲kResolved,表示解析完畢
    mirror::Class::SetStatus(h_new_class, ClassStatus::kResolved, self);
    h_new_class_out->Assign(h_new_class.Get());
  }
  return true;
}

ClassLinker::LinkMethods
LinkMethods()非常複雜,通過一個實際的代碼例子和圖解來理解linkmethod。

  • methods_:僅保存在本類中定義的direct、virtual以及拷貝過來的方法
  • vtable_或embedded_vtable_:如果類可實例化,則只存在embedded_vtable_,否則vtable_。
  • embedded_imtable_:如果類可實例化,則存在這個變量。方便快速找到接口方法。
  • iftable_:存儲該類在接口實現關係上的信息,包括繼承了哪些接口類,實際的接口方法。
public interface If0{
    public void doInterfaceWork0();
    public void doInterfaceWork1();
}
public static interface If1 extends If0{
    public void doInterfaceWork2();
    public void doInterfaceWork3();
}
public static abstract class AbsClass0 implements If1{
    public void doInterfaceWork0(){return;}
    public void doInterfaceWork3(){return;}
    abstract public void doAbsWork0();
    public void doRealWork0(){return;}
}
public static class ConcreteClass extends AbsClass0{
    public void doInterfaceWork0(){return;}
    public void doInterfaceWork1(){return;}
    public void doInterfaceWork2(){return;}
    public void doInterfaceWork3(){return;}
    public void doAbsWork0(){return;}
    public void doRealWork1(){return;}
}
public static class ConcreteChildClass extends ConcreteClass{
    public void doRealWork2(){return;}
}

ClassLinker::LinkFields
LinkInstanceFields、LinkStaticFields都調用LinkFields,核心就是計算class大小、設置ArtField的offset_變量。完成之後的內存佈局如下,不再詳細解釋,自行閱讀ClassLinker::LinkFields、Class::ComputeClassSize相關代碼。

ClassLinker::CreateReferenceInstanceOffsets
設置Class類的reference_instance_offsets_,一個32位的bitmap,提供了一種快速訪問類非靜態引用變量的方法。
reference_instance_offsets_如果某個位上爲1,說明對應的位置上有一個非靜態引用類型變量,否則爲0。如果超過32個非靜態引用對象,放棄優化,沿着派生關係向上對引用型變量查找。

void ClassLinker::CreateReferenceInstanceOffsets(Handle<mirror::Class> klass) {
  uint32_t reference_offsets = 0;
  ObjPtr<mirror::Class> super_class = klass->GetSuperClass();
  if (super_class != nullptr) {
    reference_offsets = super_class->GetReferenceInstanceOffsets();
    //kClassWalkSuper是一個特殊標誌,表示不使用優化
    if (reference_offsets != mirror::Class::kClassWalkSuper) {
      //本類包含的非靜態引用類型變量個數
      size_t num_reference_fields = klass->NumReferenceInstanceFieldsDuringLinking();
      if (num_reference_fields != 0u) {
        //計算起始位置
        uint32_t start_offset = RoundUp(super_class->GetObjectSize(),
                                        sizeof(mirror::HeapReference<mirror::Object>));
        uint32_t start_bit = (start_offset - mirror::kObjectHeaderSize) /
            sizeof(mirror::HeapReference<mirror::Object>);
        //剩餘bit位不足,則放棄優化
        if (start_bit + num_reference_fields > 32) {
          reference_offsets = mirror::Class::kClassWalkSuper;
        } else {
          //reference_offsets初值爲父類比特位,或上本類
          reference_offsets |= (0xffffffffu << start_bit) &
                               (0xffffffffu >> (32 - (start_bit + num_reference_fields)));
        }
      }
    }
  }
  klass->SetReferenceInstanceOffsets(reference_offsets);
}

接着看一段使用reference_instance_offsets_的代碼Object::VisitFieldsReferences。

template<bool kIsStatic,
         VerifyObjectFlags kVerifyFlags,
         ReadBarrierOption kReadBarrierOption,
         typename Visitor>
inline void Object::VisitFieldsReferences(uint32_t ref_offsets, const Visitor& visitor) {
  //非靜態,並且≠kClassWalkSuper
  if (!kIsStatic && (ref_offsets != mirror::Class::kClassWalkSuper)) {
    uint32_t field_offset = mirror::kObjectHeaderSize;
    while (ref_offsets != 0) {
      if ((ref_offsets & 1) != 0) {
        //如果某位比特位值爲1,則指向一個引用類型變量
        visitor(this, MemberOffset(field_offset), kIsStatic);
      }
      ref_offsets >>= 1;
      //調整field_offset的位置
      field_offset += sizeof(mirror::HeapReference<mirror::Object>);
    }
  } else {
    //如下代碼刪除了kIsStatic相關,可以看到先遍歷本類變量,再向上變量super類變量
    for (ObjPtr<Class> klass = GetClass<kVerifyFlags, kReadBarrierOption>(); klass != nullptr; klass = klass->GetSuperClass<kVerifyFlags, kReadBarrierOption>()) {
      const size_t num_reference_fields = klass->NumReferenceInstanceFields();
      MemberOffset field_offset = klass->GetFirstReferenceInstanceFieldOffset<kVerifyFlags, kReadBarrierOption>();
      for (size_t i = 0u; i < num_reference_fields; ++i) {
        if (field_offset.Uint32Value() != ClassOffset().Uint32Value()) {
          visitor(this, field_offset, kIsStatic);
        }
        field_offset = MemberOffset(field_offset.Uint32Value() +
                                    sizeof(mirror::HeapReference<mirror::Object>));
      }
    }
  }
}

3.初始化(initialize)

ART虛擬機並沒有嚴格按照java規範來實施加載類的流程,Verify會在initialize階段觸發,dex2oat階段也有Verify動作。Verify主要針對java方法,成員變量無校驗之說。Verify跟java規範關係很大,繁雜瑣碎,本篇不打算介紹細節,只關注大概流程即可。詳細可自行從ClassLinker::VerifyClass()進行追蹤。
Verify:
ClassLinker::VerifyClass()中會判斷預校驗的狀態:

bool preverified = VerifyClassUsingOatFile(dex_file, klass.Get(), oat_file_class_status);
  • 預校驗:verify可以在dex2oat階段進行,如果校驗成功,則類狀態設爲kVerified。如果出現校驗軟錯誤,則類狀態設置爲kRetryVerificationAtRuntime,之後在完整runtime運行時再校驗。
  • 狀態爲kVerified:完整runtime運行時會爲該類中的methods_數組裏的所有ArtMethod對象設置kAccSkipAccessChecks標誌,同時也爲類設置kAccVerificationAttempted標記(表示類已經校驗過,不需要再做校驗)。
  • 類狀爲kRetryVerificationAtRuntime:完整runtime運行時再校驗。

ClassLinker::InitializeClass
InitializeClass執行完畢會設置類狀態爲kInitialized,至此類已完全準備好。

bool ClassLinker::InitializeClass(Thread* self, Handle<mirror::Class> klass,
                                  bool can_init_statics, bool can_init_parents) {

    //如果類還沒有校驗,則校驗它
    if (!klass->IsVerified()) {
      VerifyClass(self, klass);
      ......
    }
  //初始化klass所實現的接口
  if (!klass->IsInterface()) {
    size_t num_direct_interfaces = klass->NumDirectInterfaces();
    if (UNLIKELY(num_direct_interfaces > 0)) {
      StackHandleScope<1> hs_iface(self);
      MutableHandle<mirror::Class> handle_scope_iface(hs_iface.NewHandle<mirror::Class>(nullptr));
      for (size_t i = 0; i < num_direct_interfaces; i++) {
        handle_scope_iface.Assign(mirror::Class::GetDirectInterface(self, klass.Get(), i));
        // 初始化接口類,並遞歸初始化接口類的父接口類
        bool iface_initialized = InitializeDefaultInterfaceRecursive(self, handle_scope_iface,
                                                                     can_init_statics, can_init_parents);
      }
    }
  }

  //初始化klass中的靜態成員變量。class_def結構體的static_values_off代表該類靜態成員變量初始值存儲位置。
  const size_t num_static_fields = klass->NumStaticFields();
  if (num_static_fields > 0) {
    //找到klass對應的ClassDef信息
    const DexFile::ClassDef* dex_class_def = klass->GetClassDef();
    StackHandleScope<3> hs(self);
    Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader()));
    //找到對應的DexCache對象
    Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
    ......
    //遍歷ClassDef中代表Static_values_off
    annotations::RuntimeEncodedStaticFieldValueIterator value_it(dex_cache,
                                                                 class_loader,
                                                                 this,
                                                                 *dex_class_def);
    const DexFile& dex_file = *dex_cache->GetDexFile();
    const uint8_t* class_data = dex_file.GetClassData(*dex_class_def);
    ClassDataItemIterator field_it(dex_file, class_data);
    if (value_it.HasNext()) {
      for ( ; value_it.HasNext(); value_it.Next(), field_it.Next()) {
        //找到對應的ArtField成員
        ArtField* field = ResolveField(field_it.GetMemberIndex(), dex_cache, class_loader, /* is_static */ true);
        //設置ArtField的初值,在ArtField的offset_上設置初值。
        value_it.ReadValueToField<true>(field);
      }
    }
  }
  //找到類的"<clinit>"函數,並執行它
  if (!self->IsExceptionPending()) {
    ArtMethod* clinit = klass->FindClassInitializer(image_pointer_size_);
    if (clinit != nullptr) {
      JValue result;
      clinit->Invoke(self, nullptr, 0, &result, "V");
    }
  }
......
      //設置類狀態爲kInitialized,至此類已完全準備好
      mirror::Class::SetStatus(klass, ClassStatus::kInitialized, self);
      //靜態成員靜態方法在linkcode時會設置trampoline入口地址,初始化完成後設置真正的入口地址
      FixupStaticTrampolines(klass.Get());
......
  return success;
}
參考資料
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章