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