广告位联系
返回顶部
分享到

Android类加载流程分析

Android 来源:互联网 作者:佚名 发布时间:2022-10-08 23:09:57 人浏览
摘要

本文分析的代码基于Android8.1.0源码。 流程分析 从loadClass开始,我们来看下Android中类加载的流程 /libcore/ojluni/src/main/java/java/lang/ClassLoader.java::loadClass loadClass流程如下: 1 2 3 4 5 6 7 8 9 10

本文分析的代码基于Android8.1.0源码。

流程分析

从loadClass开始,我们来看下Android中类加载的流程

/libcore/ojluni/src/main/java/java/lang/ClassLoader.java::loadClass

loadClass流程如下:

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

protected Class<?> loadClass(String name, boolean resolve)

    throws ClassNotFoundException

{

        // First, check if the class has already been loaded

        Class<?> c = findLoadedClass(name);

        if (c == null) {

            try {

                if (parent != null) {

                    c = parent.loadClass(name, false);

                } else {

                    c = findBootstrapClassOrNull(name);

                }

            } catch (ClassNotFoundException e) {

                // ClassNotFoundException thrown if class not found

                // from the non-null parent class loader

            }

 

            if (c == null) {

                // If still not found, then invoke findClass in order

                // to find the class.

                c = findClass(name);

            }

        }

        return c;

}

/libcore/ojluni/src/main/java/java/lang/ClassLoader.java::findClass

1

2

3

protected Class<?> findClass(String name) throws ClassNotFoundException {

       throw new ClassNotFoundException(name);

   }

ClassLoader类的findClass是没有实际查找代码的,所以调用findClass其实是调用其实现类的findClass函数,例如:BaseDexClassLoader

/libcore/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java::findClass

每个BaseDexClassLoader都持有一个DexPathList,BaseDexClassLoader的findClass类调用了DexPathList的findClass。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

@Override

protected Class<?> findClass(String name) throws ClassNotFoundException {

    List<Throwable> suppressedExceptions = new ArrayList<Throwable>();

    Class c = pathList.findClass(name, suppressedExceptions);

    if (c == null) {

        ClassNotFoundException cnfe = new ClassNotFoundException(

                "Didn't find class \"" + name + "\" on path: " + pathList);

        for (Throwable t : suppressedExceptions) {

            cnfe.addSuppressed(t);

        }

        throw cnfe;

    }

    return c;

}

/libcore/dalvik/src/main/java/dalvik/system/DexPathList.java::findClass

遍历所有dexElements,并调用Element类的findClass。

1

2

3

4

5

6

7

8

9

10

11

12

13

public Class<?> findClass(String name, List<Throwable> suppressed) {

    for (Element element : dexElements) {

        Class<?> clazz = element.findClass(name, definingContext, suppressed);

        if (clazz != null) {

            return clazz;

        }

    }

 

    if (dexElementsSuppressedExceptions != null) {

        suppressed.addAll(Arrays.asList(dexElementsSuppressedExceptions));

    }

    return null;

}

题外话,dexElements对象其实是DexPathList$Element类的数组,用于存储已加载的dex或者jar的信息。

/libcore/dalvik/src/main/java/dalvik/system/DexPathList$Element::findClass

Element的findClass,又去调用DexFile类的loadClassBinaryName,可以理解为在单独的dex或者jar对象中加载类

1

2

3

4

5

public Class<?> findClass(String name, ClassLoader definingContext,

                List<Throwable> suppressed) {

            return dexFile != null ? dexFile.loadClassBinaryName(name, definingContext, suppressed)

                    : null;

        }

libcore\dalvik\src\main\java\dalvik\system\DexFile.java::loadClassBinaryName

去调用defineClass函数

1

2

3

public Class loadClassBinaryName(String name, ClassLoader loader, List<Throwable> suppressed) {

        return defineClass(name, loader, mCookie, this, suppressed);

    }

libcore\dalvik\src\main\java\dalvik\system\DexFile.java::defineClass

调用defineClassNative,准备进入Native层

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

private static Class defineClass(String name, ClassLoader loader, Object cookie,

                                 DexFile dexFile, List<Throwable> suppressed) {

    Class result = null;

    try {

        result = defineClassNative(name, loader, cookie, dexFile);

    } catch (NoClassDefFoundError e) {

        if (suppressed != null) {

            suppressed.add(e);

        }

    } catch (ClassNotFoundException e) {

        if (suppressed != null) {

            suppressed.add(e);

        }

    }

    return result;

}

art\runtime\native\dalvik_system_DexFile.cc::DexFile_defineClassNative

检查dex是否加载,类名是否合理,并遍历DexFile对象,查找Dex文件中的类的定义,找到就去调用ClassLinker::DefineClass函数。

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

54

55

56

57

static jclass DexFile_defineClassNative(JNIEnv* env,

                                        jclass,

                                        jstring javaName,

                                        jobject javaLoader,

                                        jobject cookie,

                                        jobject dexFile) {

  std::vector<const DexFile*> dex_files;

  const OatFile* oat_file;

  if (!ConvertJavaArrayToDexFiles(env, cookie, /*out*/ dex_files, /*out*/ oat_file)) {

    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 =

        OatDexFile::FindClassDef(*dex_file, descriptor.c_str(), hash);

    if (dex_class_def != nullptr) {

      ScopedObjectAccess soa(env);

      ClassLinker* class_linker = Runtime::Current()->GetClassLinker();

      StackHandleScope<1> hs(soa.Self());

      Handle<mirror::ClassLoader> class_loader(

          hs.NewHandle(soa.Decode<mirror::ClassLoader>(javaLoader)));

      ObjPtr<mirror::DexCache> dex_cache =

          class_linker->RegisterDexFile(*dex_file, class_loader.Get());

      if (dex_cache == nullptr) {

        // OOME or InternalError (dexFile already registered with a different class loader).

        soa.Self()->AssertPendingException();

        return nullptr;

      }

      ObjPtr<mirror::Class> result = class_linker->DefineClass(soa.Self(),

                                                               descriptor.c_str(),

                                                               hash,

                                                               class_loader,

                                                               *dex_file,

                                                               *dex_class_def);

      // Add the used dex file. This only required for the DexFile.loadClass API since normal

      // class loaders already keep their dex files live.

      class_linker->InsertDexFileInToClassLoader(soa.Decode<mirror::Object>(dexFile),

                                                 class_loader.Get());

      if (result != nullptr) {

        VLOG(class_linker) << "DexFile_defineClassNative returning " << result

                           << " for " << class_name.c_str();

        return soa.AddLocalReference<jclass>(result);

      }

    }

  }

  VLOG(class_linker) << "Failed to find dex_class_def " << class_name.c_str();

  return nullptr;

}

art\runtime\class_linker.cc::DefineClass

DefineClass这个函数做了许多工作,相当于底层类加载逻辑的分发器,整体逻辑如下图:

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

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

mirror::Class* ClassLinker::DefineClass(Thread* self,

                                        const char* descriptor,

                                        size_t hash,

                                        Handle<mirror::ClassLoader> class_loader,

                                        const DexFile& dex_file,

                                        const DexFile::ClassDef& dex_class_def) {

   

  StackHandleScope<3> hs(self);

  auto klass = hs.NewHandle<mirror::Class>(nullptr);

 

  ......

 

  // Get the real dex file. This will return the input if there aren't any callbacks or they do

  // nothing.

  DexFile const* new_dex_file = nullptr;

  DexFile::ClassDef const* new_class_def = nullptr;

  // TODO We should ideally figure out some way to move this after we get a lock on the klass so it

  // will only be called once.

  Runtime::Current()->GetRuntimeCallbacks()->ClassPreDefine(descriptor,

                                                            klass,

                                                            class_loader,

                                                            dex_file,

                                                            dex_class_def,

                                                            &new_dex_file,

                                                            &new_class_def);

  // Check to see if an exception happened during runtime callbacks. Return if so.

  if (self->IsExceptionPending()) {

    return nullptr;

  }

  ObjPtr<mirror::DexCache> dex_cache = RegisterDexFile(*new_dex_file, class_loader.Get());

  if (dex_cache == nullptr) {

    self->AssertPendingException();

    return nullptr;

  }

  klass->SetDexCache(dex_cache);

  SetupClass(*new_dex_file, *new_class_def, klass, class_loader.Get());

 

  // Mark the string class by setting its access flag.

  if (UNLIKELY(!init_done_)) {

    if (strcmp(descriptor, "Ljava/lang/String;") == 0) {

      klass->SetStringClass();

    }

  }

 

  ObjectLock<mirror::Class> lock(self, klass);

  klass->SetClinitThreadId(self->GetTid());

  // Make sure we have a valid empty iftable even if there are errors.

  klass->SetIfTable(GetClassRoot(kJavaLangObject)->GetIfTable());

 

  // Add the newly loaded class to the loaded classes table.

  ObjPtr<mirror::Class> existing = InsertClass(descriptor, klass.Get(), hash);

  if (existing != nullptr) {

    // We failed to insert because we raced with another thread. Calling EnsureResolved may cause

    // this thread to block.

    return EnsureResolved(self, descriptor, existing);

  }

 

  // Load the fields and other things after we are inserted in the table. This is so that we don't

  // end up allocating unfree-able linear alloc resources and then lose the race condition. The

  // other reason is that the field roots are only visited from the class table. So we need to be

  // inserted before we allocate / fill in these fields.

  LoadClass(self, *new_dex_file, *new_class_def, klass);

  if (self->IsExceptionPending()) {

    VLOG(class_linker) << self->GetException()->Dump();

    // An exception occured during load, set status to erroneous while holding klass' lock in case

    // notification is necessary.

    if (!klass->IsErroneous()) {

      mirror::Class::SetStatus(klass, mirror::Class::kStatusErrorUnresolved, self);

    }

    return nullptr;

  }

 

  // Finish loading (if necessary) by finding parents

  CHECK(!klass->IsLoaded());

  if (!LoadSuperAndInterfaces(klass, *new_dex_file)) {

    // Loading failed.

    if (!klass->IsErroneous()) {

      mirror::Class::SetStatus(klass, mirror::Class::kStatusErrorUnresolved, self);

    }

    return nullptr;

  }

  CHECK(klass->IsLoaded());

 

  // At this point the class is loaded. Publish a ClassLoad event.

  // Note: this may be a temporary class. It is a listener's responsibility to handle this.

  Runtime::Current()->GetRuntimeCallbacks()->ClassLoad(klass);

 

  // Link the class (if necessary)

  CHECK(!klass->IsResolved());

  // TODO: Use fast jobjects?

  auto interfaces = hs.NewHandle<mirror::ObjectArray<mirror::Class>>(nullptr);

 

  MutableHandle<mirror::Class> h_new_class = hs.NewHandle<mirror::Class>(nullptr);

  if (!LinkClass(self, descriptor, klass, interfaces, &h_new_class)) {

    // Linking failed.

    if (!klass->IsErroneous()) {

      mirror::Class::SetStatus(klass, mirror::Class::kStatusErrorUnresolved, self);

    }

    return nullptr;

  }

  self->AssertNoPendingException();

  CHECK(h_new_class != nullptr) << descriptor;

  CHECK(h_new_class->IsResolved() && !h_new_class->IsErroneousResolved()) << descriptor;

 

  // Instrumentation may have updated entrypoints for all methods of all

  // classes. However it could not update methods of this class while we

  // were loading it. Now the class is resolved, we can update entrypoints

  // as required by instrumentation.

  if (Runtime::Current()->GetInstrumentation()->AreExitStubsInstalled()) {

    // We must be in the kRunnable state to prevent instrumentation from

    // suspending all threads to update entrypoints while we are doing it

    // for this class.

    DCHECK_EQ(self->GetState(), kRunnable);

    Runtime::Current()->GetInstrumentation()->InstallStubsForClass(h_new_class.Get());

  }

 

  /*

   * We send CLASS_PREPARE events to the debugger from here.  The

   * definition of "preparation" is creating the static fields for a

   * class and initializing them to the standard default values, but not

   * executing any code (that comes later, during "initialization").

   *

   * We did the static preparation in LinkClass.

   *

   * The class has been prepared and resolved but possibly not yet verified

   * at this point.

   */

  Runtime::Current()->GetRuntimeCallbacks()->ClassPrepare(klass, h_new_class);

 

  // Notify native debugger of the new class and its layout.

  jit::Jit::NewTypeLoadedIfUsingJit(h_new_class.Get());

 

  return h_new_class.Get();

}

art\runtime\class_linker.cc::SetupClass

SetupClass设置类的一些基本字段信息。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

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函数判断类是否在列表中:

  • 如果在列表中,则直接返回;
  • 如果没有,则添加到列表。

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

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;

}

art\runtime\class_linker.cc::LoadClass

LoadClass函数获取了dex文件中的classData部分,然后去调用LoadClassMembers

1

2

3

4

5

6

7

8

9

10

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;  // 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

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

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

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 case

        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++;

    }

    ......

}

art\runtime\class_linker.cc::LoadField

LoadField设置ArtField结构中字段的一些值

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());

}

art\runtime\class_linker.cc::LoadMethod

LoadMethod函数主要做设置ArtMethod结构的一些属性,比如函数的MethodIdx,CodeItem在dex文件中的偏移,函数的AccessFlag等。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

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_);

     

    ScopedAssertNoThreadSuspension ants("LoadMethod");

    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();

     

    ......

     

    dst->SetAccessFlags(access_flags);

}

延申:ArtMethod是存储Java函数在虚拟机内相关信息的结构,它不同于mirror命名空间下的Method类,ArtMethod在Java层没有类与之直接映射。

art\runtime\class_linker.cc::LinkCode

LinkCode函数主要功能是判断代码是否编译从而为函数设置入口代码。

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

static void LinkCode(ClassLinker* class_linker,

                     ArtMethod* method,

                     const OatFile::OatClass* oat_class,

                     uint32_t class_def_method_index){

  Runtime* const runtime = Runtime::Current();

  if (runtime->IsAotCompiler()) {

    // The following code only applies to a non-compiler runtime.

    return;

  }

  // Method shouldn't have already been linked.

  DCHECK(method->GetEntryPointFromQuickCompiledCode() == nullptr);

  if (oat_class != nullptr) {

    // Every kind of method should at least get an invoke stub from the oat_method.

    // non-abstract methods also get their code pointers.

    const OatFile::OatMethod oat_method = oat_class->GetOatMethod(class_def_method_index);

    oat_method.LinkMethod(method);

  }

 

  // Install entry point from interpreter.

  const void* quick_code = method->GetEntryPointFromQuickCompiledCode();

  bool enter_interpreter = class_linker->ShouldUseInterpreterEntrypoint(method, quick_code);

 

  if (!method->IsInvokable()) {

    EnsureThrowsInvocationError(class_linker, method);

    return;

  }

 

  if (method->IsStatic() && !method->IsConstructor()) {

    // For static methods excluding the class initializer, install the trampoline.

    // It will be replaced by the proper entry point by ClassLinker::FixupStaticTrampolines

    // after initializing class (see ClassLinker::InitializeClass method).

    method->SetEntryPointFromQuickCompiledCode(GetQuickResolutionStub());

  } else if (quick_code == nullptr && method->IsNative()) {

    method->SetEntryPointFromQuickCompiledCode(GetQuickGenericJniStub());

  } else if (enter_interpreter) {

    // Set entry point from compiled code if there's no code or in interpreter only mode.

    method->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());

  }

 

  if (method->IsNative()) {

    // Unregistering restores the dlsym lookup stub.

    method->UnregisterNative();

 

    if (enter_interpreter || quick_code == nullptr) {

      // We have a native method here without code. Then it should have either the generic JNI

      // trampoline as entrypoint (non-static), or the resolution trampoline (static).

      // TODO: this doesn't handle all the cases where trampolines may be installed.

      const void* entry_point = method->GetEntryPointFromQuickCompiledCode();

      DCHECK(class_linker->IsQuickGenericJniStub(entry_point) ||

             class_linker->IsQuickResolutionStub(entry_point));

    }

  }

}


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 : https://www.cnblogs.com/luoyesiqiu/p/classload.html
相关文章
  • Kotlin的Collection与Sequence操作异同点介绍

    Kotlin的Collection与Sequence操作异同点介绍
    在Android开发中,集合是我们必备的容器,Kotlin的标准库中提供了很多处理集合的方法,而且还提供了两种基于容器的工作方式:Collection 和
  • 实现一个Kotlin函数类型方法

    实现一个Kotlin函数类型方法
    接口与函数类型 业务开发中,经常会有实现一个函数式接口(即接口只有一个方法需要实现)的场景,大家应该都会不假思索的写出如下代
  • Android10 App启动Activity源码分析
    ActivityThread的main方法 让我们把目光聚焦到ActivityThread的main方法上。 ActivityThread的源码路径为/frameworks/base/core/java/android/app/ActivityThread。 1 2
  • Android10客户端事务管理ClientLifecycleManager源码解析

    Android10客户端事务管理ClientLifecycleManager源码解析
    在Android 10 App启动分析之Activity启动篇(二)一文中,简单地介绍了Activity的生命周期管理器是如何调度Activity进入onCreate生命周期的流程。这
  • Kotlin对象的懒加载方式by lazy与lateinit异同介绍

    Kotlin对象的懒加载方式by lazy与lateinit异同介绍
    属性或对象的延时加载是我们相当常用的,一般我们都是使用 lateinit 和 by lazy 来实现。 他们两者都是延时初始化,那么在使用时那么他们两
  • Android类加载流程分析

    Android类加载流程分析
    本文分析的代码基于Android8.1.0源码。 流程分析 从loadClass开始,我们来看下Android中类加载的流程 /libcore/ojluni/src/main/java/java/lang/ClassLoader.ja
  • Android实现读写USB串口数据的代码

    Android实现读写USB串口数据的代码
    最近在研究USB方面的内容;先后做了关于Android读写HID、串口设备的DEMO。本文比较简单,主要介绍的是Android实现读取串口数据的功能 废话不
  • Epoxy - 在RecyclerView中构建复杂界面
    Diffing 对于复杂数据结构支持的多个视图类型展示在屏幕上, Epoxy此时是尤其有用的. 在这些场景中, 数据可能会被网络请求, 异步 Observable, 用
  • Android性能优化的详细介绍

    Android性能优化的详细介绍
    性能优化是一个app很重要的一部分,一个性能优良的app从被下载到启动到使用都能给用户到来很好的体验。自然我们做性能优化也是从被下
  • Android进阶宝典-插件化2(Hook启动插件中四大组件

    Android进阶宝典-插件化2(Hook启动插件中四大组件
    在上一节,我们主要介绍了如果通过反射来加载插件中的类,调用类中的方法;既然插件是一个apk,其实最重要的是启动插件中的Activity、
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计