ART 加载类

一.创建Activity对象

ART在加载完dex文件后,会通过Instrumentation创建Activity对象

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ...
    Activity activity = null;
    try {
        //加载dex文件
        java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
        //创建Activity对象
        activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
        StrictMode.incrementExpectedActivityCount(activity.getClass());
        r.intent.setExtrasClassLoader(cl);
        r.intent.prepareToEnterProcess();
        if (r.state != null) {
            r.state.setClassLoader(cl);
        }
    } catch (Exception e) {
        if (!mInstrumentation.onException(activity, e)) {
            throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
        }
    }
    ...
}

1. Instrumentation.newActivity()

public Activity newActivity(ClassLoader cl, String className,
            Intent intent)
            throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
    return (Activity)cl.loadClass(className).newInstance();
}

从之前的加载dex文件的过程中可以知道这里传入的ClassLoaderPathClassLoader

以我自己写的demo为例,PathClassLoader是:

dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.singuloid.myapplication-1/base.apk"],
  nativeLibraryDirectories=[/data/app/com.singuloid.myapplication-1/lib/arm, /system/lib, /vendor/lib]]]

PathClassLoader继承自BaseDexClassLoader,而BaseDexClassLoader又是继承自ClassLoader,PathClassLoaderBaseDexClassLoader两个类都没有重写loadClass(),所以这里实际调用的基类ClassLoader.loadClass

2. ClassLoader.loadClass()

protected Class loadClass(String className, boolean resolve) throws ClassNotFoundException {
    //先查找之前是否已经过要加载的类, [2.1]
    Class c = findLoadedClass(name);
    if (c == null) {
        long t0 = System.nanoTime();
        try {
            if (parent != null) {
                 //在parent中查找类
                 c = parent.loadClass(name, false);
            } else {
                 //如果parent为null,则代表当前ClassLoader是BootClassLoader
                 c = findBootstrapClassOrNull(name);
            }
         } catch (ClassNotFoundException e) {
                // ClassNotFoundException thrown if class not found
                // from the non-null parent class loader
         }

          if (c == null) {         
              long t1 = System.nanoTime();
              c = findClass(name);
          }
      }
      return c;
}

从代码中可以看出,ART的类加载机制也同样采用双亲委派模式,即先由父ClassLoader进行加载,如果没有加载成功,再交由子ClassLoader加载,依照此顺序,依次向下进行.
如果查找的是应用自己的类,如果没有加载过,最后都会在应用自己的ClassLoader中查找

如果父类加载器没有加载到类,则调用当前类加载器的findClass方法,在创建Activity对象这个场景下,当前的类加载器是PathClassLoader,而PathClassLoader并没有重写findClass,查看其父类BaseDexClassLoader,发现BaseDexClassLoader重写了findClass这个方法

2.1 ClassLoader.findLoadedClass

protected final Class findLoadedClass(String name) {
    ClassLoader loader;
    if (this == BootClassLoader.getInstance())
        loader = null;
    else
        loader = this;
    return VMClassLoader.findLoadedClass(loader, name);
}

VMClassLoader.findLoadedClass是一个native方法,其实现在art/runtime/native/lava_lang_VMClassLoader

static jclass VMClassLoader_findLoadedClass(JNIEnv* env, jclass, jobject javaLoader,
                                            jstring javaName) {
  ScopedFastNativeObjectAccess soa(env);
  mirror::ClassLoader* loader = soa.Decode(javaLoader);
  ScopedUtfChars name(env, javaName);
  if (name.c_str() == nullptr) {
    return nullptr;
  }
  ClassLinker* cl = Runtime::Current()->GetClassLinker();
  std::string descriptor(DotToDescriptor(name.c_str()));
  const size_t descriptor_hash = ComputeModifiedUtf8Hash(descriptor.c_str());
  //在传入的ClassLoader中查找类,每一个ClassLoader都有一个ClassTable,用来记录已经加载的类
  mirror::Class* c = cl->LookupClass(soa.Self(), descriptor.c_str(), descriptor_hash, loader);
  //如果找到类,且类已经被正确解析,则直接返回
  if (c != nullptr && c->IsResolved()) {
    return soa.AddLocalReference(c);
  }
  //如果类是错误的,则抛出相应异常
  if (c != nullptr && c->IsErroneous()) {
    ...
    return nullptr;
  }
  //执行到这里,意味着没有在缓存的ClassTable中找到类,需要进一步到dex文件中进行查找
  if (loader != nullptr) {
    StackHandleScope<1> hs(soa.Self());
    cl->FindClassInPathClassLoader(soa, soa.Self(), descriptor.c_str(), descriptor_hash,
                                   hs.NewHandle(loader), &c);
    if (c != nullptr) {
      return soa.AddLocalReference(c);
    }
  }
  // Class wasn't resolved so it may be erroneous or not yet ready, force the caller to go into
  // the regular loadClass code.
  return nullptr;
}

3. BaseDexClassLoader.findClass()

@Override
protected Class findClass(String name) throws ClassNotFoundException {
    List suppressedExceptions = new ArrayList();
    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;
}

由之前的ART 加载dex文件可知,BaseDexClassLoaderpathList变量指向的是一个DexPathList,而DexPathList是用来保存加载的dex文件列表,从这里我们知道BaseDexClassLoader又将加载类的过程委派给了DexPathList

4. DexPathList.findClass()

public Class findClass(String name, List suppressed) {
    //迭代dexElements
    for (Element element : dexElements) {
        DexFile dex = element.dexFile;

        if (dex != null) {
            Class clazz = dex.loadClassBinaryName(name, definingContext, suppressed);
            if (clazz != null) {
                return clazz;
            }
        }
    }
    if (dexElementsSuppressedExceptions != null) {
        suppressed.addAll(Arrays.asList(dexElementsSuppressedExceptions));
    }
    return null;
}

从代码中可知,其主要逻辑是遍历之前加载过得dex文件列表,依次在每个dex文件中查找,直到加载到相应的类

5. DexFile.loadClassBinaryName()

public Class loadClassBinaryName(String name, ClassLoader loader, List suppressed) {
    //mCookie保存的是加载的dex文件列表
    return defineClass(name, loader, mCookie, suppressed);
}

private static Class defineClass(String name, ClassLoader loader, Object cookie,
                                     List suppressed) {
    Class result = null;
    try {
        result = defineClassNative(name, loader, cookie);
    } catch (NoClassDefFoundError e) {
        if (suppressed != null) {
            suppressed.add(e);
        }
    } catch (ClassNotFoundException e) {
        if (suppressed != null) {
            suppressed.add(e);
        }
    }
    return result;
}

private static native Class defineClassNative(String name, ClassLoader loader, Object cookie)
            throws ClassNotFoundException, NoClassDefFoundError;

loadClassBinaryName实际就是封装调用了defineClass(从代码中可以看出,传入的参数中有一个是mCookie,这个变量保存的正是之前加载的dex文件列表),而defineClass实际调用的是native方法defineClassNative,只是额外做了异常处理.defineClassNative的实现在art/runtime/native/dalvik_system_DexFile.cc

6. DexFile_defineClassNative()

static jclass DexFile_defineClassNative(JNIEnv* env, jclass, jstring javaName, jobject javaLoader,
                                        jobject cookie) {
    //将Java层传入的mCookie变量转换为vector类型的dex文件列表
    std::unique_ptr> dex_files = ConvertJavaArrayToNative(env, cookie);
    ...

    ScopedUtfChars class_name(env, javaName);
    ...
    //将com.xx.xx转换为com/xx/xx
    const std::string descriptor(DotToDescriptor(class_name.c_str()));
    const size_t hash(ComputeModifiedUtf8Hash(descriptor.c_str()));

    for (auto& dex_file : *dex_files) {
        //首先获取ClassDef
        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();
            StackHandleScope<1> hs(soa.Self());
            Handle class_loader(
                hs.NewHandle(soa.Decode(javaLoader)));

            //生成dex_cache,并放入缓存队列, [6.1]
            class_linker->RegisterDexFile(*dex_file, class_loader.Get());
            //加载类,[7]
            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(dexFile),
                                                  class_loader.Get());
            if (result != nullptr) {
                ...
                return soa.AddLocalReference(result);
            }
        }
    }
    return nullptr;
}
  1. defineClassNative第一个关键步骤是将Java层传入的mCookie变量转换为Native的vector类型的dex文件列表
  2. 在Native层,每个dex文件有一个对应的DexCache结构,该结构缓存了dex文件中一些基本的信息
  3. 遍历dex文件列表时,首先从dex文件中获取ClassDef结构,之后再根据这个ClassDef来加载相应的类

6.1 ClassLinker::RegisterDexFile()

mirror::DexCache* ClassLinker::RegisterDexFile(const DexFile& dex_file,
                                               mirror::ClassLoader* class_loader) {
  Thread* self = Thread::Current();
  {
      ReaderMutexLock mu(self, dex_lock_);
      //查找是由已经有对应的dex_cache,有则直接返回
      mirror::DexCache* dex_cache = FindDexCacheLocked(self, dex_file, true);
      if (dex_cache != nullptr) {
          return dex_cache;
      }
  }
  //获取ClassLoader对应的LinearAlloc
  LinearAlloc* const linear_alloc = GetOrCreateAllocatorForClassLoader(class_loader);
  DCHECK(linear_alloc != nullptr);
  ClassTable* table;
  {
      WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
      //获取ClassLoader的ClassTable
      table = InsertClassTableForClassLoader(class_loader);
  }

  StackHandleScope<1> hs(self);
  //在LinearAlloc创建一个dex_cache结构,此时不要持有dex_lock_锁,因为分配时可能会挂起所有线程而且可能存在线程需要
  //dex_lock_
  Handle h_dex_cache(hs.NewHandle(AllocDexCache(self, dex_file, linear_alloc)));
  {
      WriterMutexLock mu(self, dex_lock_);
      mirror::DexCache* dex_cache = FindDexCacheLocked(self, dex_file, true);
      if (dex_cache != nullptr) {
        return dex_cache;
      }
      //如果分配dex_cache结构失败,则一定是发生了OOM
      if (h_dex_cache.Get() == nullptr) {
        self->AssertPendingOOMException();
        return nullptr;
      }
      //根据dex_file生成dex_cache,并注册dex_cache
      RegisterDexFileLocked(dex_file, h_dex_cache);
  }
  table->InsertStrongRoot(h_dex_cache.Get());
  return h_dex_cache.Get();
}

7. ClassLinker::DefineClass

mirror::Class* ClassLinker::DefineClass(Thread* self, const char* descriptor, size_t hash,
                                        Handle class_loader,
                                        const DexFile& dex_file,
                                        const DexFile::ClassDef& dex_class_def) {

    StackHandleScope<3> hs(self);
    auto klass = hs.NewHandle(nullptr);

    //如果ClassLinker还未初始化完成,且要加载的正好是几个指定的系统类,将kclass指向系统类
    ...

    if (klass.Get() == nullptr) {
        //创建Class对象
        klass.Assign(AllocClass(self, SizeOfClassWithoutEmbeddedTables(dex_file, dex_class_def)));
    }

    ...
    //获取dex_cache结构,如果未获取到则创建
    mirror::DexCache* dex_cache = RegisterDexFile(dex_file, class_loader.Get());
    if (dex_cache == nullptr) {
        self->AssertPendingOOMException();
        return nullptr;
    }
    klass->SetDexCache(dex_cache);
    //设置klass基本属性, [7.1]
    SetupClass(dex_file, dex_class_def, klass, class_loader.Get());

    ...

    ObjectLock lock(self, klass);
    klass->SetClinitThreadId(self->GetTid());

    // 将要加载的类添加到ClassLinker的已加载类列表
    mirror::Class* existing = InsertClass(descriptor, klass.Get(), hash);
    if (existing != nullptr) {
        //如果插入失败,则表明类已经被加载过
        return EnsureResolved(self, descriptor, existing);
    }
    //加载类,[7.2]
    LoadClass(self, dex_file, dex_class_def, klass);
    ...

    CHECK(!klass->IsLoaded());
    if (!LoadSuperAndInterfaces(klass, dex_file)) {
        ...
    }
    //正常情况下,此时klass->IsLoaded = true
    CHECK(klass->IsLoaded());
    //正常情况下,此时klass->isResolved = false
    CHECK(!klass->IsResolved());
    auto interfaces = hs.NewHandle>(nullptr);

    MutableHandle h_new_class = hs.NewHandle(nullptr);
    //对加载后的类进行链接解析,[7.3]
    if (!LinkClass(self, descriptor, klass, interfaces, &h_new_class)) {
        ...
    }
    ...
    return h_new_class.Get();
}

DefineClass中的关键步骤可以总结为:SetupClass-->InsertClass-->LoadClass-->LoadSuperAndInterfaces-->LinkClass

7.1 ClassLinker::SetupClass

void ClassLinker::SetupClass(const DexFile& dex_file,
                             const DexFile::ClassDef& dex_class_def,
                             Handle klass,
                             mirror::ClassLoader* class_loader) {
  ... //Check(...)
  const char* descriptor = dex_file.GetClassDescriptor(dex_class_def);
  ... //Check(...)

  klass->SetClass(GetClassRoot(kJavaLangClass));
  uint32_t access_flags = dex_class_def.GetJavaAccessFlags();
  ... //Check(...)

  klass->SetAccessFlags(access_flags);
  klass->SetClassLoader(class_loader);
  ... //Check(...)

  mirror::Class::SetStatus(klass, mirror::Class::kStatusIdx, nullptr);

  klass->SetDexClassDefIndex(dex_file.GetIndexForClassDef(dex_class_def));
  klass->SetDexTypeIndex(dex_class_def.class_idx_);
  ... //Check(...)
}

可以看到,SetupClass方法主要是给Class对象设置基本属性如access_flags,ClassLoader

7.2 ClassLinker::LoadClass()

void ClassLinker::LoadClass(Thread* self, const DexFile& dex_file,
                            const DexFile::ClassDef& dex_class_def,
                            Handle klass) {
    //获取ClassData
    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
    }
    bool has_oat_class = false;
    if (Runtime::Current()->IsStarted() && !Runtime::Current()->IsAotCompiler()) {
        //获取OatClass,通过OatClass可以获取类方法的本地机器指令
        //klass->GetDexClassDefIndex()获取相应ClassDef结构在dex文件内的索引号,这个索引号是在之前的
        //SetupClass()函数中获取并设置
        OatFile::OatClass oat_class = FindOatClass(dex_file, klass->GetDexClassDefIndex(),
                                                   &has_oat_class);
        if (has_oat_class) {
            //加载类成员, [7.2.1]
            LoadClassMembers(self, dex_file, class_data, klass, &oat_class);
        }
    }
    if (!has_oat_class) {
        LoadClassMembers(self, dex_file, class_data, klass, nullptr);
    }
}
  1. 从dex文件内部获取ClassData结构
  2. 根据ClassDef的索引位置获取相应OatClass结构,通过OatClass结构可以获取类方法的本地机器指令
  3. 如果找到OatClass则根据OatClass来加载类成员

dex文件中每一个类在oat文件中都由一个对应的OatClass结构,根据OatClass可以找到每一个类方法的本地机器指令

7.2.1 ClassLinker::LoadClassMembers()
void ClassLinker::LoadClassMembers(Thread* self,
                                   const DexFile& dex_file,
                                   const uint8_t* class_data,
                                   Handle klass,
                                   const OatFile::OatClass* oat_class) {
    {
      //在没有加载完类成员之前,不允许当前线程挂起
      ScopedAssertNoThreadSuspension nts(self, __FUNCTION__);
      //加载静态属性
      LinearAlloc* const allocator = GetAllocatorForClassLoader(klass->GetClassLoader());
      ClassDataItemIterator it(dex_file, class_data);
      LengthPrefixedArray* 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)) {
            //加载属性,[7.2.1.1]
            LoadField(it, klass, &sfields->At(num_sfields));
            ++num_sfields;
            last_field_idx = field_idx;
          }
      }


      //加载实例属性
      LengthPrefixedArray* 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();
          if (num_ifields == 0 || LIKELY(field_idx > last_field_idx)) {
            LoadField(it, klass, &ifields->At(num_ifields));
            ++num_ifields;
            last_field_idx = field_idx;
          }
        }
      ....
      // Set the field arrays.
      klass->SetSFieldsPtr(sfields);
      klass->SetIFieldsPtr(ifields);

      // 加载方法
      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_);
          //加载方法,[7.2.1.2]
          LoadMethod(self, dex_file, it, klass, method);
          //将方法同对应的本地机器指令关联,这样在方法执行时就可以知道该如何执行, [7.2.1.3]
          LinkCode(method, oat_class, 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(self, dex_file, it, klass, method);
          LinkCode(method, oat_class, class_def_method_index);
          class_def_method_index++;
      }
    }
    // Ensure that the card is marked so that remembered sets pick up native roots.
    Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(klass.Get());
    self->AllowThreadSuspension();
}
  1. 首先便是设置当前线程在没有完成加载类成员工作之前不能被挂起
  2. 之后依次加载Static Field,Instance Field,所有Field都用ArtField表示
  3. 加载完Field后,再依次加载Direct Method和Virtual Method并关联Method对应的机器指令,所有Method都用ArtMethod表示
  4. 当所有加载工作完成之后,告知线程加载工作完成,允许被挂起
7.2.1.1 ClassLinker::LoadField()
void ClassLinker::LoadField(const ClassDataItemIterator& it, Handle klass,
                            ArtField* dst) {
    const uint32_t field_idx = it.GetMemberIndex();
    dst->SetDexFieldIndex(field_idx);
    dst->SetDeclaringClass(klass.Get());
    dst->SetAccessFlags(it.GetFieldAccessFlags());
}
7.2.1.2 ClassLinker::LoadMethod()
void ClassLinker::LoadMethod(Thread* self, const DexFile& dex_file, const ClassDataItemIterator& it,
                             Handle klass, ArtMethod* dst) {
    //从dex文件的ClassData结构种获取对应Method的索引
    uint32_t dex_method_idx = it.GetMemberIndex();
    //获取MethodId结构
    const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx);
    const char* method_name = dex_file.StringDataByIdx(method_id.name_idx_);

    ScopedAssertNoThreadSuspension ants(self, "LoadMethod");
    dst->SetDexMethodIndex(dex_method_idx);
    dst->SetDeclaringClass(klass.Get());
    dst->SetCodeItemOffset(it.GetMethodCodeItemOffset());

    dst->SetDexCacheResolvedMethods(klass->GetDexCache()->GetResolvedMethods());
    dst->SetDexCacheResolvedTypes(klass->GetDexCache()->GetResolvedTypes());

    uint32_t access_flags = it.GetMethodAccessFlags();

    //一般情况下,方法名不会是finalize
    if (UNLIKELY(strcmp("finalize", method_name) == 0)) {
        // Set finalizable flag on declaring class.
        if (strcmp("V", dex_file.GetShorty(method_id.proto_idx_)) == 0) {
            // Void return type.
            if (klass->GetClassLoader() != nullptr) {  // All non-boot finalizer methods are flagged.
                klass->SetFinalizable();
            } else {
                std::string temp;
                const char* klass_descriptor = klass->GetDescriptor(&temp);
                //Enum枚举类不设置finalizable,因为枚举类已经声明了一个final finalize()
                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("", method_name) == 0);
        //判断是不是类初始化方法
        bool is_clinit = !is_init && (strcmp("", method_name) == 0);
        if (UNLIKELY(!is_init && !is_clinit)) {
            ... //LOG
        } else {
            if (UNLIKELY((access_flags & kAccConstructor) == 0)) {
                access_flags |= kAccConstructor;
            }
        }
    }
    dst->SetAccessFlags(access_flags);
}
7.2.1.3 ClassLinker::LinkCode()
void ClassLinker::LinkCode(ArtMethod* method, const OatFile::OatClass* oat_class,
                             uint32_t class_def_method_index) {
    Runtime* const runtime = Runtime::Current();
    if (runtime->IsAotCompiler()) {
        return;
    }
    ...

    if (oat_class != nullptr) {
        //从OatClass中获取对应的OatMethod,OatMethod中记录了方法的本地机器指令的偏移地址
        //通过OatMethod::LinkMethod将OatMethod中记录的信息设置到ArtMethod当中
        const OatFile::OatMethod oat_method = oat_class->GetOatMethod(class_def_method_index);
        oat_method.LinkMethod(method);
    }

    //之后设置方法执行的entry point
    //判断是否需要解释执行:
    //1.当没有本地机器指令
    //2.Runtime指定以Interpreter方式运行且方法不是native同时也不是proxy
    //JNI方法是没有对应的DEX字节码的,因此即使ART虚拟机运行在解释模式中,JNI方法也不能通过解释器来执行
    bool enter_interpreter = NeedsInterpreter(method, method->GetEntryPointFromQuickCompiledCode());
    if (enter_interpreter && !method->IsNative()) {
        method->SetEntryPointFromInterpreter(artInterpreterToInterpreterBridge);
    } else {
        //有两种情况会进入这一分支
        //不需要解释执行的方法
        //没有本地机器指令或者Runtime以Interpreter方式运行,但该方法是native
        method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);
    }

    if (method->IsAbstract()) {
        //抽象方法没有机器指令,当有机器指令的方法调用抽象方法时,需要设置一个桥接函数,从而转到
        //解释器,由解释器解释执行抽象方法
        method->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());
        return;
    }

    if (method->IsStatic() && !method->IsConstructor()) {
        method->SetEntryPointFromQuickCompiledCode(GetQuickResolutionStub());
    } else if (enter_interpreter) {
        if (!method->IsNative()) {
            method->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());
        } else {
            //只有当native方法没有本地机器指令时,会执行这一分支
            method->SetEntryPointFromQuickCompiledCode(GetQuickGenericJniStub());
        }
    }

    if (method->IsNative()) {
        // Unregistering restores the dlsym lookup stub.
        method->UnregisterNative();

        if (enter_interpreter) {
          //native方法且没有对应的机器指令,则该方法如果是non-static,则entry point是generic JNI trampoline
          //如果是static, 则entry point是resolution trampoline
          const void* entry_point = method->GetEntryPointFromQuickCompiledCode();
          DCHECK(IsQuickGenericJniStub(entry_point) || IsQuickResolutionStub(entry_point));
        }
    }
}

LinkCode方法主要作用是根据方法属性来设置entry point

  1. 对于需要解释的方法,该方法需要由解释器解释执行,当另一个解释方法调用了这个需要解释执行的方法时,该方法的入口函数是artInterpreterToInterpreterBridge,从而继续在解释器中解释执行;如果当前方法是执行本地机器指令,当另一个解释执行的方法调用了这个执行本地机器指令的方法,该方法的入口函数是artInterpreterToCompiledCodeBridgeartInterpreterToCompiledCodeBridge会去调用相应的机器指令
  2. 抽象方法需要由被子类实现,所以抽象类是没有本地机器指令的,需要由解释器解释执行,当有机器指令的方法调用抽象方法时, 需要设置一个桥接函数,从而转到
    解释器,由解释器解释执行抽象方法, 这个桥接函数是GetQuickToInterpreterBridge()
  3. 对于静态非构造函数,当有执行机器指令的方法调用这类函数时,入口函数是GetQuickResolutionStub().因为静态方法不需要创建对象便可执行,着就有可能出现类还未初始化,方法就要执行,所以此时就需要现将类初始化,再执行静态方法,GetQuickResolutionStub完成的正是这项工作
  4. 对于需要解释执行且不是native的方法,当执行本地机器指令的方法调用该方法时,入口函数是GetQuickToInterpreterBridge(),该函数会转到解释器,由解释器执行这个需要解释执行的方法;当一个执行本地机器指令的方法调用没有机器指令的native方法时,入口函数是GetQuickGenericJniStub()
  5. 如果一个方法是native方法,设置本地方法的入口是通过GetJniDlsymLookupStub获得的一个Stub

以上内容参考老罗的Android运行时ART加载类和方法的过程分析

8. ClassLinker::InsertDexFileInToClassLoader

void ClassLinker::InsertDexFileInToClassLoader(mirror::Object* dex_file,
                                               mirror::ClassLoader* class_loader) {
    Thread* const self = Thread::Current();
    WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
    ClassTable* const table = ClassTableForClassLoader(class_loader);
    //InsertStrongRoot方法将dex_file对象放入ClassTable的strong_table_队列中
    if (table->InsertStrongRoot(dex_file) && class_loader != nullptr) {
        //执行write barrier从而让GC知道ClassLoader的ClassTable发生了改变
        Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(class_loader);
    }
}

你可能感兴趣的:(ART 加载类)