Android类加载流程

移动安全 2年前 (2022) admin
364 0 0

背景

由于前前前阵子写了个壳,得去了解类的加载流程,当时记了一些潦草的笔记。这几天把这些东西简单梳理了一下,本文分析的代码基于Android8.1.0源码。

流程分析

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

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

loadClass流程如下:

Android类加载流程

protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
Class<?> c = findLoadedClass(name);
if (c == null) {
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
}

if (c == null) {
c = findClass(name);
}
}
return c;
}

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

    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。

@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。

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对象中加载类

 public Class<?> findClass(String name, ClassLoader definingContext,
List<Throwable> suppressed) {
return dexFile != null ? dexFile.loadClassBinaryName(name, definingContext, suppressed)
: null;
}

libcoredalviksrcmainjavadalviksystemDexFile.java::loadClassBinaryName

去调用defineClass函数

public Class loadClassBinaryName(String name, ClassLoader loader, List<Throwable> suppressed) {
return defineClass(name, loader, mCookie, this, suppressed);
}

libcoredalviksrcmainjavadalviksystemDexFile.java::defineClass

调用defineClassNative,准备进入Native层

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

artruntimenativedalvik_system_DexFile.cc::DexFile_defineClassNative

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

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

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

artruntimeclass_linker.cc::DefineClass

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

Android类加载流程

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

......

DexFile const* new_dex_file = nullptr;
DexFile::ClassDef const* new_class_def = nullptr;
Runtime::Current()->GetRuntimeCallbacks()->ClassPreDefine(descriptor,
klass,
class_loader,
dex_file,
dex_class_def,
&new_dex_file,
&new_class_def);
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());

if (UNLIKELY(!init_done_)) {
if (strcmp(descriptor, "Ljava/lang/String;") == 0) {
klass->SetStringClass();
}
}

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

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

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

return EnsureResolved(self, descriptor, existing);
}

LoadClass(self, *new_dex_file, *new_class_def, klass);
if (self->IsExceptionPending()) {
VLOG(class_linker) << self->GetException()->Dump();

if (!klass->IsErroneous()) {
mirror::Class::SetStatus(klass, mirror::Class::kStatusErrorUnresolved, self);
}
return nullptr;
}

CHECK(!klass->IsLoaded());
if (!LoadSuperAndInterfaces(klass, *new_dex_file)) {

if (!klass->IsErroneous()) {
mirror::Class::SetStatus(klass, mirror::Class::kStatusErrorUnresolved, self);
}
return nullptr;
}
CHECK(klass->IsLoaded());

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

CHECK(!klass->IsResolved());
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)) {

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;

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

DCHECK_EQ(self->GetState(), kRunnable);
Runtime::Current()->GetInstrumentation()->InstallStubsForClass(h_new_class.Get());
}

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

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

return h_new_class.Get();
}

在DefineClass里面也能看到许多mirror::Class::SetStatus()函数的调用,用来设置Class的加载状态。它可以有以下几种状态:

enum Status {
kStatusRetired = -3, // Retired, should not be used. Use the newly cloned one instead.
kStatusErrorResolved = -2,
kStatusErrorUnresolved = -1,
kStatusNotReady = 0,
kStatusIdx = 1, // Loaded, DEX idx in super_class_type_idx_ and interfaces_type_idx_.
kStatusLoaded = 2, // DEX idx values resolved.
kStatusResolving = 3, // Just cloned from temporary class object.
kStatusResolved = 4, // Part of linking.
kStatusVerifying = 5, // In the process of being verified.
kStatusRetryVerificationAtRuntime = 6, // Compile time verification failed, retry at runtime.
kStatusVerifyingAtRuntime = 7, // Retrying verification at runtime.
kStatusVerified = 8, // Logically part of linking; done pre-init.
kStatusSuperclassValidated = 9, // Superclass validation part of init done.
kStatusInitializing = 10, // Class init in progress.
kStatusInitialized = 11, // Ready to go.
kStatusMax = 12,
};

延申:mirror命名空间下的类是底层对Java层类的映射,比如上面的mirror::Class类就是对java.lang.Class类的映射,SetAccessFlags就是对Class类的accessFlags字段赋值。

artruntimeclass_linker.cc::SetupClass

SetupClass设置类的一些基本字段信息。并把Class加载状态设置为kStatusIdx

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

artruntimeclass_linker.cc::InsertClass

InsertClass函数判断类是否在列表中:

  • 如果在列表中,则直接返回

  • 如果没有,则添加到列表

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) {
Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(class_loader);
}
if (log_new_roots_) {
new_class_roots_.push_back(GcRoot<mirror::Class>(klass));
}
}
if (kIsDebugBuild) {
for (ArtMethod& method : klass->GetCopiedMethods(image_pointer_size_)) {
CHECK_EQ(GetHoldingClassOfCopiedMethod(&method), klass);
}
}
return nullptr;
}

对于InsertClass结果不为空的情况,表示类已经在加载表中了。

这种情况下,调用EnsureResolved来等待类过期并且重新加载完成

mirror::Class* ClassLinker::EnsureResolved(Thread* self,
const char* descriptor,
ObjPtr<mirror::Class> klass)
{

......

if (init_done_ && klass->IsTemp()) {
CHECK(!klass->IsResolved());
if (klass->IsErroneousUnresolved()) {
ThrowEarlierClassFailure(klass);
return nullptr;
}
StackHandleScope<1> hs(self);
Handle<mirror::Class> h_class(hs.NewHandle(klass));
ObjectLock<mirror::Class> lock(self, h_class);
while (!h_class->IsRetired() && !h_class->IsErroneousUnresolved()) {
lock.WaitIgnoringInterrupts();
}
if (h_class->IsErroneousUnresolved()) {
ThrowEarlierClassFailure(h_class.Get());
return nullptr;
}
CHECK(h_class->IsRetired());
klass = LookupClass(self, descriptor, h_class.Get()->GetClassLoader());
}

size_t index = 0;

static const size_t kNumYieldIterations = 1000;

static const size_t kSleepDurationUS = 1000; // 1 ms.
while (!klass->IsResolved() && !klass->IsErroneousUnresolved()) {
StackHandleScope<1> hs(self);
HandleWrapperObjPtr<mirror::Class> h_class(hs.NewHandleWrapper(&klass));
{
ObjectTryLock<mirror::Class> lock(self, h_class);

if (lock.Acquired()) {
if (!h_class->IsResolved() && h_class->GetClinitThreadId() == self->GetTid()) {
ThrowClassCircularityError(h_class.Get());
mirror::Class::SetStatus(h_class, mirror::Class::kStatusErrorUnresolved, self);
return nullptr;
}
}
}
{
ScopedThreadSuspension sts(self, kSuspended);
if (index < kNumYieldIterations) {
sched_yield();
} else {
usleep(kSleepDurationUS);
}
}
++index;
}

if (klass->IsErroneousUnresolved()) {
ThrowEarlierClassFailure(klass);
return nullptr;
}
CHECK(klass->IsResolved()) << klass->PrettyClass();
self->AssertNoPendingException();
return klass.Ptr();
}

然后将EnsureResolved函数的返回的Class作为DefineClass函数的返回值

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)
{
......

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

return EnsureResolved(self, descriptor, existing);
}

......
}

artruntimeclass_linker.cc::LoadClass

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

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;
}
LoadClassMembers(self, dex_file, class_data, klass);
}

artruntimeclass_linker.cc::LoadClassMembers

LoadClassMembers函数主要逻辑是遍历类中的所有字段和函数,然后分别调用LoadField,LoadMethod和LinkCode

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

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);
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) {
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++;
}
......
}

artruntimeclass_linker.cc::LoadField

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

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

artruntimeclass_linker.cc::LoadMethod

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

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层没有类与之直接映射。

artruntimeclass_linker.cc::LinkCode

LinkCode函数主要功能是判断代码是否编译,以及函数的类型来为函数设置入口代码。

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()) {
return;
}
DCHECK(method->GetEntryPointFromQuickCompiledCode() == nullptr);
if (oat_class != nullptr) {
const OatFile::OatMethod oat_method = oat_class->GetOatMethod(class_def_method_index);
oat_method.LinkMethod(method);
}

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()) {
method->SetEntryPointFromQuickCompiledCode(GetQuickResolutionStub());
} else if (quick_code == nullptr && method->IsNative()) {
method->SetEntryPointFromQuickCompiledCode(GetQuickGenericJniStub());
} else if (enter_interpreter) {
method->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());
}

if (method->IsNative()) {
method->UnregisterNative();

if (enter_interpreter || quick_code == nullptr) {
const void* entry_point = method->GetEntryPointFromQuickCompiledCode();
DCHECK(class_linker->IsQuickGenericJniStub(entry_point) ||
class_linker->IsQuickResolutionStub(entry_point));
}
}
}

跟到这里,DefineClass里面的流程已经过了一半了,接下来继续来跟LinkClass那一分支。

从LinkClass函数定义来看,LinkClass有一个参数是h_new_class_out,它是一个指针,并且根据变量名猜测,它是会被LinkClass修改和赋值的

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

看DefineClass里调用LinkClass的代码,它传了一个为nullptr的h_new_class进去,也印证了上面的猜想:


......

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

......

artruntimeclass_linker.cc::LinkClass

LinkClass中调用LinkSuperClass、LinkMethods、LinkInstanceFields和LinkStaticFields这些函数。接着给h_new_class_out分配一个值。这个值返回到DexFile_defineClassNative转成jclass,jclass到Java层就变成了java.lang.Class

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)
{
CHECK_EQ(mirror::Class::kStatusLoaded, klass->GetStatus());

if (!LinkSuperClass(klass)) {
return false;
}
ArtMethod* imt_data[ImTable::kSize];
bool new_conflict = false;
std::fill_n(imt_data, arraysize(imt_data), Runtime::Current()->GetImtUnimplementedMethod());
if (!LinkMethods(self, klass, interfaces, &new_conflict, imt_data)) {
return false;
}
if (!LinkInstanceFields(self, klass)) {
return false;
}
size_t class_size;
if (!LinkStaticFields(self, klass, &class_size)) {
return false;
}
CreateReferenceInstanceOffsets(klass);
CHECK_EQ(mirror::Class::kStatusLoaded, klass->GetStatus());

ImTable* imt = nullptr;
if (klass->ShouldHaveImt()) {

if (!new_conflict) {
ImTable* super_imt = FindSuperImt(klass.Get(), image_pointer_size_);
if (super_imt != nullptr) {
bool imt_equals = true;
for (size_t i = 0; i < ImTable::kSize && imt_equals; ++i) {
imt_equals = imt_equals && (super_imt->Get(i, image_pointer_size_) == imt_data[i]);
}
if (imt_equals) {
imt = super_imt;
}
}
}
if (imt == nullptr) {
LinearAlloc* allocator = GetAllocatorForClassLoader(klass->GetClassLoader());
imt = reinterpret_cast<ImTable*>(
allocator->Alloc(self, ImTable::SizeInBytes(image_pointer_size_)));
if (imt == nullptr) {
return false;
}
imt->Populate(imt_data, image_pointer_size_);
}
}

if (!klass->IsTemp() || (!init_done_ && klass->GetClassSize() == class_size)) {
CHECK_EQ(klass->GetClassSize(), class_size) << klass->PrettyDescriptor();

if (klass->ShouldHaveEmbeddedVTable()) {
klass->PopulateEmbeddedVTable(image_pointer_size_);
}
if (klass->ShouldHaveImt()) {
klass->SetImt(imt, image_pointer_size_);
}

if (cha_ != nullptr) {
cha_->UpdateAfterLoadingOf(klass);
}

mirror::Class::SetStatus(klass, mirror::Class::kStatusResolved, self);
h_new_class_out->Assign(klass.Get());
} else {
CHECK(!klass->IsResolved());

StackHandleScope<1> hs(self);
auto h_new_class = hs.NewHandle(klass->CopyOf(self, class_size, imt, image_pointer_size_));

klass->SetMethodsPtrUnchecked(nullptr, 0, 0);
klass->SetSFieldsPtrUnchecked(nullptr);
klass->SetIFieldsPtrUnchecked(nullptr);
if (UNLIKELY(h_new_class == nullptr)) {
self->AssertPendingOOMException();
mirror::Class::SetStatus(klass, mirror::Class::kStatusErrorUnresolved, self);
return false;
}

CHECK_EQ(h_new_class->GetClassSize(), class_size);
ObjectLock<mirror::Class> lock(self, h_new_class);
FixupTemporaryDeclaringClass(klass.Get(), h_new_class.Get());

{
WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
ObjPtr<mirror::ClassLoader> const class_loader = h_new_class.Get()->GetClassLoader();
ClassTable* const table = InsertClassTableForClassLoader(class_loader);
ObjPtr<mirror::Class> existing = table->UpdateClass(descriptor, h_new_class.Get(),
ComputeModifiedUtf8Hash(descriptor));
if (class_loader != nullptr) {
Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(class_loader);
}
CHECK_EQ(existing, klass.Get());
if (log_new_roots_) {
new_class_roots_.push_back(GcRoot<mirror::Class>(h_new_class.Get()));
}
}

if (cha_ != nullptr) {
cha_->UpdateAfterLoadingOf(h_new_class);
}

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

CHECK_EQ(h_new_class->GetStatus(), mirror::Class::kStatusResolving);

mirror::Class::SetStatus(h_new_class, mirror::Class::kStatusResolved, self);

h_new_class_out->Assign(h_new_class.Get());
}
return true;
}

后记

本文只是跟踪了loadClass的大体流程,还有许多东西没有展开,比如LinkMethods。如有兴趣,可以自行研究。


原文始发于微信公众号(luoyesiqiu):Android类加载流程

版权声明:admin 发表于 2022年10月6日 下午2:08。
转载请注明:Android类加载流程 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...