美文网首页
Android 如何保证并发场景下class只会被加载一次?

Android 如何保证并发场景下class只会被加载一次?

作者: ZuYuan | 来源:发表于2023-03-13 22:21 被阅读0次

本文基于Android10的classlinker的源码,分析了linker对于class加载是怎么保证并发安全的。

简化DefineClass流程

ObjPtr<mirror::Class> ClassLinker::DefineClass() { 
  auto klass = hs.NewHandle<mirror::Class>(nullptr);
  //分配一个Class的空间
  klass.Assign(AllocClass(self, SizeOfClassWithoutEmbeddedTables(dex_file, dex_class_def)));
  //注册dex file,这一步不会重复注册,就不再分析了
  ObjPtr<mirror::DexCache> dex_cache = RegisterDexFile(*new_dex_file, class_loader.Get());
  //对klass加锁
  ObjectLock<mirror::Class> lock(self, klass);
  //安装class,把class的基本信息设置好
  SetupClass(*new_dex_file, *new_class_def, klass, class_loader.Get());
  //注册到ClassTable,后续就可以直接从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);
  }
  //加载
  LoadClass();
  //链接
  LinkClass();
  //...
}

重点一、InsertClass

InsertClass函数

重点二、EnsureResolved

InsertClass()执行结束之后,klass还会经过加载、链接、初始化流程,如何确保最终返回的class经过了这些流程呢?
根据重点一,可知DefineClass()方法中的ObjectLock<mirror::Class> lock(self, klass)同样会持有klass的锁直到DefineClass方法的结束。而EnsureResolved恰好利用了这一点,让其它线程通过竞争klass锁的方式,确保klass的Define流程结束:

EnsureResolved关键代码

相关文章

网友评论

      本文标题:Android 如何保证并发场景下class只会被加载一次?

      本文链接:https://www.haomeiwen.com/subject/ktchrdtx.html