return mClassLoader;
}
1.3 ApplicationLoaders.getClassLoader
public ClassLoader getClassLoader(String zip, String libPath, ClassLoader parent){
//Class.getSystemClassLoader返回的是一个PathClassLoader
//baseParent是BootClassLoader
ClassLoader baseParent = ClassLoader.getSystemClassLoader().getParent();
synchronized (mLoaders) {
if (parent == null) {
parent = baseParent;
}
if (parent == baseParent) {
ClassLoader loader = mLoaders.get(zip);
if (loader != null) {
return loader;
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, zip);
//创建一个PathClassLoader,并放入缓存,方便以后直接获取
PathClassLoader pathClassloader =
new PathClassLoader(zip, libPath, parent);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
mLoaders.put(zip, pathClassloader);
return pathClassloader;
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, zip);
PathClassLoader pathClassloader = new PathClassLoader(zip, parent);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
return pathClassloader;
}
}
1.4 PathClassLoader()
public PathClassLoader(String dexPath, String libraryPath,
ClassLoader parent) {
//PathClassLoader继承自BaseDexClassLoader,所以会调用
//BaseDexClassLoader的构造函数
super(dexPath, null, libraryPath, parent);
}
1.5 BaseDexClassLoader()
//由PathClassLoader传入的参数可以知道第二个参数optimizedDirectory=null
public BaseDexClassLoader(String dexPath, File optimizedDirectory,
String libraryPath, ClassLoader parent) {
super(parent);
this.pathList = new DexPathList(this, dexPath, libraryPath, optimizedDirectory);
}
1.6 DexPathList()
public DexPathList(ClassLoader definingContext, String dexPath,
String libraryPath, File optimizedDirectory) {
…
this.definingContext = definingContext;
ArrayList suppressedExceptions = new ArrayList();
//加载dex文件
this.dexElements = makePathElements(splitDexPath(dexPath), optimizedDirectory,
suppressedExceptions);
this.nativeLibraryDirectories = splitPaths(libraryPath, false);
this.systemNativeLibraryDirectories =
splitPaths(System.getProperty(“java.library.path”), true);
List allNativeLibraryDirectories = new ArrayList<>(nativeLibraryDirectories);
allNativeLibraryDirectories.addAll(systemNativeLibraryDirectories);
//加载library文件
this.nativeLibraryPathElements = makePathElements(allNativeLibraryDirectories, null,
suppressedExceptions);
…
1.7 DexPathList.makePathElements()
private static Element[] makePathElements(List files, File optimizedDirectory,
List suppressedExceptions) {
List elements = new ArrayList<>();
for (File file : files) {
File zip = null;
File dir = new File(“”);
DexFile dex = null;
String path = file.getPath();
String name = file.getName();
if (path.contains(zipSeparator)) {
String split[] = path.split(zipSeparator, 2);
zip = new File(split[0]);
dir = new File(split[1]);
} else if (file.isDirectory()) {
//如果file是library会执行这一分支
elements.add(new Element(file, true, null, null));
} else if (file.isFile()) {
if (name.endsWith(DEX_SUFFIX)) {
//如果文件以.dex结尾,直接加载
try {
dex = loadDexFile(file, optimizedDirectory);
} catch (IOException ex) {
System.logE("Unable to load dex file: " + file, ex);
}
} else {
zip = file;
//加载位于.zip或者.apk文件内的dex文件
try {
dex = loadDexFile(file, optimizedDirectory);
} catch (IOException suppressed) {
suppressedExceptions.add(suppressed);
}
}
} else {
System.logW("ClassLoader referenced unknown path: " + file);
}
if ((zip != null) || (dex != null)) {
elements.add(new Element(dir, false, zip, dex));
}
}
return elements.toArray(new Element[elements.size()]);
}
1.8 DexPathList.loadDexFile()
private static DexFile loadDexFile(File file, File optimizedDirectory)
throws IOException {
if (optimizedDirectory == null) {
//如果是PathClassLoader,则执行这一步
return new DexFile(file);
} else {
//首先确保输出后的文件是以.dex结尾
String optimizedPath = optimizedPathFor(file, optimizedDirectory);
return DexFile.loadDex(file.getPath(), optimizedPath, 0);
}
}
1.8.1 DexFile(String fileName)
public DexFile(String fileName) throws IOException {
//mCookie是一个Object类型的对象,用这个对象来保存dex文件也可能是dex文件列表
//之后在加载class的时候,会把这个对象传入,从而加载相应的class
mCookie = openDexFile(fileName, null, 0);
mFileName = fileName;
guard.open(“close”);
}
1.8.2 DexFile.loadDex()
static public DexFile loadDex(String sourcePathName, String outputPathName,
int flags) throws IOException {
return new DexFile(sourcePathName, outputPathName, flags);
}
1.8.3 DexFile()
private DexFile(String sourceName, String outputName, int flags) throws IOException {
if (outputName != null) {
try {
String parent = new File(outputName).getParent();
//确保输出目录属于当前应用,即输出目录是应用的私有目录/data/data/package_name/xxx
if (Libcore.os.getuid() != Libcore.os.stat(parent).st_uid) {
throw new IllegalArgumentException("Optimized data directory " + parent
-
" is not owned by the current user. Shared storage cannot protect"
-
" your application from code injection attacks.");
}
} catch (ErrnoException ignored) {
}
}
//mCookie是一个Object类型的对象,用这个对象来保存dex文件也可能是dex文件列表
//之后在加载class的时候,会把这个对象传入,从而加载相应的class
mCookie = openDexFile(sourceName, outputName, flags);
mFileName = sourceName;
guard.open(“close”);
}
从以上代码片段中可以看出,最后加载dex文件都是调用DexFile.openDexFile
这个方法
1.9. DexFile.openDexFile()
private static Object openDexFile(String sourceName, String outputName, int flags) throws IOException {
return openDexFileNative(new File(sourceName).getAbsolutePath(),
(outputName == null) ? null : new File(outputName).getAbsolutePath(),
flags);
}
openDexFileNative
是一个native方法,之后的调用进入native层
[](http
s://blog.csdn.net/weixin_47933729/article/details/113146251)2.1 DexFile_openDexFileNative()
static jobject DexFile_openDexFileNative(
JNIEnv* env, jclass, jstring javaSourceName, jstring javaOutputName, jint) {
…
ClassLinker* linker = Runtime::Current()->GetClassLinker();
std::vector<std::unique_ptr> dex_files;
std::vectorstd::string error_msgs;
dex_files = linker->OpenDexFilesFromOat(sourceName.c_str(), outputName.c_str(), &error_msgs);
if (!dex_files.empty()) {
jlongArray array = ConvertNativeToJavaArray(env, dex_files);
… //错误处理,释放相应资源
//返回给Java层,由DexFile的mCookie指向
return array;
} else {
… //抛出异常
return nullptr;
}
}
2.2 ClassLinker::OpenDexFilesFromOat()
std::vector<std::unique_ptr> ClassLinker::OpenDexFilesFromOat(
const char* dex_location, const char* oat_location,
std::vectorstd::string* error_msgs) {
CHECK(error_msgs != nullptr);
// Verify we aren’t holding the mutator lock, which could starve GC if we
// have to generate or relocate an oat file.
Locks::mutator_lock_->AssertNotHeld(Thread::Current());
//Runtime::Current()->IsAotCompiler用来判断Runtime是否用于dex2oat,dex2oat程序
//也会创建一个Runtime,专门用来Compile
OatFileAssistant oat_file_assistant(dex_location, oat_location, kRuntimeISA,
!Runtime::Current()->IsAotCompiler());
// Lock the target oat location to avoid races generating and loading the
// oat file.
std::string error_msg;
if (!oat_file_assistant.Lock(&error_msg)) {
…
}
// Check if we already have an up-to-date oat file open.
const OatFile* source_oat_file = nullptr;
{
ReaderMutexLock mu(Thread::Current(), dex_lock_);
//oat_file_变量属于ClassLinker,用来存放oat文件
for (const OatFile* oat_file : oat_files_) {
…
// 判断oat文件是否正确
if (oat_file_assistant.GivenOatFileIsUpToDate(*oat_file)) {
source_oat_file = oat_file;
break;
}
}
}
// If we didn’t have an up-to-date oat file open, try to load one from disk.
if (source_oat_file == nullptr) {
// Update the oat file on disk if we can. This may fail, but that’s okay.
// Best effort is all that matters here.
// 根据dex文件产生对应的oat文件
if (!oat_file_assistant.MakeUpToDate(&error_msg)) {
…
}
// Get the oat file on disk.
std::unique_ptr oat_file = oat_file_assistant.GetBestOatFile();
if (oat_file.get() != nullptr) {
// Take the file only if it has no collisions, or we must take it because of preopting.
bool accept_oat_file = !HasCollisions(oat_file.get(), &error_msg);
if (!accept_oat_file) {
…
// However, if the app was part of /system and preopted, there is no original dex file
// available. In that case grudgingly accept the oat file.
if (!DexFile::MaybeDex(dex_location)) {
accept_oat_file = true;
…
}
}
if (accept_oat_file) {
source_oat_file = oat_file.release();
//将oat_file添加至oat_file_
RegisterOatFile(source_oat_file);
}
}
}
std::vector<std::unique_ptr> dex_files;
// Load the dex files from the oat file.
if (source_oat_file != nullptr) {
//通过OatFileAssistant加载dex文件
dex_files = oat_file_assistant.LoadDexFiles(*source_oat_file, dex_location);
if (dex_files.empty()) {
…
}
}
// Fall back to running out of the original dex file if we couldn’t load any
// dex_files from the oat file.
if (dex_files.empty()) {
…
}
return dex_files;
}
2.3 OatFileAssistant::LoadDexFiles()
std::vector<std::unique_ptr> OatFileAssistant::LoadDexFiles(
const OatFile& oat_file, const char* dex_location) {
std::vector<std::unique_ptr> dex_files;
//先加载主dex文件.
//先从OatFile中获取OatDexFile, 在oat文件中每一个OatDexFile记录了相应的
//dex文件的文件名,文件偏移地址等关键信息
std::string error_msg;
const OatFile::OatDexFile* oat_dex_file = oat_file.GetOatDexFile(
dex_location, nullptr, false);
if (oat_dex_file == nullptr) {
…
return std::vector<std::unique_ptr>();
}
//通过OatDexFile加载主dex, [2.4]
std::unique_ptr dex_file = oat_dex_file->OpenDexFile(&error_msg);
if (dex_file.get() == nullptr) {
LOG(WARNING) << "Failed to open dex file from oat dex file: " << error_msg;
return std::vector<std::unique_ptr>();
}
dex_files.push_back(std::move(dex_file));
//加载其余的次级dex文件
for (size_t i = 1; ; i++) {
//先获取次级dex文件的索引位置
std::string secondary_dex_location = DexFile::GetMultiDexLocation(i, dex_location);
//根据索引位置获取对应的OatDexFile结构
oat_dex_file = oat_file.GetOatDexFile(secondary_dex_location.c_str(), nullptr, false);
if (oat_dex_file == nullptr) {
// There are no more secondary dex files to load.
break;
}
//加载次级dex文件
dex_file = oat_dex_file->OpenDexFile(&error_msg);
if (dex_file.get() == nullptr) {
LOG(WARNING) << "Failed to open dex file from oat dex file: " << error_msg;
return std::vector<std::unique_ptr>();
}
dex_files.push_back(std::move(dex_file));
}
return dex_files;
}
每一个dex文件的信息都被封装在一个OatDexFile中
OatDexFile数据结构:
const OatFile* const oat_file_
:指向oat文件的指针
const std::string dex_file_location_
:dex文件名
const std::string_canonical_dex_file_location_
:dex文件绝对路径
const uint32_t dex_file_location_cheksum_
:dex文件名的校验和
const uint8_t* const dex_file_pointer_
:指向对应dex文件在oat文件中相对于oatdata的偏移地址
const uint32_t* const oat_class_offsets_pointer_
:指向属于该dex文件的OatClass相对于oatdata的偏移地址
2.4 OatDexFile::OpenDexFile()
std::unique_ptr OatFile::OatDexFile::OpenDexFile(std::string* error_msg) const {
return DexFile::Open(dex_file_pointer_, FileSize(), dex_file_location_,
dex_file_location_checksum_, this, error_msg);
}
2.5 DexFile::Open()
static std::unique_ptr Open(const uint8_t* base, size_t size,
const std::string& location,
最后
小编这些年深知大多数初中级Android工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
资料⬅专栏获取
g.csdn.net/weixin_47933729/article/details/113146251)2.4 OatDexFile::OpenDexFile()
std::unique_ptr OatFile::OatDexFile::OpenDexFile(std::string* error_msg) const {
return DexFile::Open(dex_file_pointer_, FileSize(), dex_file_location_,
dex_file_location_checksum_, this, error_msg);
}
2.5 DexFile::Open()
static std::unique_ptr Open(const uint8_t* base, size_t size,
const std::string& location,
最后
小编这些年深知大多数初中级Android工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
[外链图片转存中…(img-uyIqHBKL-1719051994206)]
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
资料⬅专栏获取