一.创建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文件的过程中可以知道这里传入的ClassLoader
是PathClassLoader
以我自己写的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
,PathClassLoader
和BaseDexClassLoader
两个类都没有重写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文件可知,BaseDexClassLoader
的pathList
变量指向的是一个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;
}
-
defineClassNative
第一个关键步骤是将Java层传入的mCookie
变量转换为Native的vector
类型的dex文件列表 - 在Native层,每个dex文件有一个对应的DexCache结构,该结构缓存了dex文件中一些基本的信息
- 遍历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);
}
}
- 从dex文件内部获取ClassData结构
- 根据ClassDef的索引位置获取相应OatClass结构,通过OatClass结构可以获取类方法的本地机器指令
- 如果找到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();
}
- 首先便是设置当前线程在没有完成加载类成员工作之前不能被挂起
- 之后依次加载Static Field,Instance Field,所有Field都用ArtField表示
- 加载完Field后,再依次加载Direct Method和Virtual Method并关联Method对应的机器指令,所有Method都用ArtMethod表示
- 当所有加载工作完成之后,告知线程加载工作完成,允许被挂起
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
- 对于需要解释的方法,该方法需要由解释器解释执行,当另一个解释方法调用了这个需要解释执行的方法时,该方法的入口函数是
artInterpreterToInterpreterBridge
,从而继续在解释器中解释执行;如果当前方法是执行本地机器指令,当另一个解释执行的方法调用了这个执行本地机器指令的方法,该方法的入口函数是artInterpreterToCompiledCodeBridge
,artInterpreterToCompiledCodeBridge
会去调用相应的机器指令 - 抽象方法需要由被子类实现,所以抽象类是没有本地机器指令的,需要由解释器解释执行,当有机器指令的方法调用抽象方法时, 需要设置一个桥接函数,从而转到
解释器,由解释器解释执行抽象方法, 这个桥接函数是GetQuickToInterpreterBridge()
- 对于静态非构造函数,当有执行机器指令的方法调用这类函数时,入口函数是
GetQuickResolutionStub()
.因为静态方法不需要创建对象便可执行,着就有可能出现类还未初始化,方法就要执行,所以此时就需要现将类初始化,再执行静态方法,GetQuickResolutionStub
完成的正是这项工作 - 对于需要解释执行且不是native的方法,当执行本地机器指令的方法调用该方法时,入口函数是
GetQuickToInterpreterBridge()
,该函数会转到解释器,由解释器执行这个需要解释执行的方法;当一个执行本地机器指令的方法调用没有机器指令的native方法时,入口函数是GetQuickGenericJniStub()
- 如果一个方法是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);
}
}