Dex2oat流程
dex2oat 主函数
sequenceDiagram
participant Main as main函数
participant Dex2oatMain as Dex2oat函数
participant Dex2OatObj as Dex2Oat 对象实例
Main ->>Dex2oatMain: 调用 Dex2oat(argc, argv)
activate Dex2oatMain
Dex2oatMain->>Dex2OatObj: 创建并初始化Dex2Oat对象
activate Dex2OatObj
Dex2OatObj->Dex2OatObj: ParseArgs(argc, argv)解析命令行参数
Dex2oatMain->>Dex2oatMain: 初始化Memmap数据结构的静态参数 art::MemMap::Init()
opt HasProfileInput()存在配置文件输入
Dex2oatMain->Dex2OatObj: LoadProfile()加载配置文件
end
Dex2OatObj->>Dex2OatObj: UpdateCompilerOptionsBasedOnProfile()和InsertCompileOptions更新与插入编译器选项
Dex2OatObj->>Dex2OatObj: OpenFile()打开输出文件
Dex2oatMain->Dex2OatObj: 创建ScopedDex2oatReporting初始化错误报告机制
Dex2OatObj->>Dex2OatObj: 执行 dex2oat->Setup()
opt DoProfileGuidedOptimizations()执行配置文件引导优化
Dex2OatObj->>Dex2OatObj: VerifyProfileData()验证配置文件数据
end
Dex2OatObj->>Dex2OatObj: DoCompilation执行核心编译
Dex2OatObj ->> Dex2oatMain : 返回编译结果ReturnCode
deactivate Dex2OatObj
Dex2oatMain ->> Main: 返回编译结果
deactivate Dex2oatMain
Dex2Oat对象成员方法
ParseArgs
解析命令行参数。如果遇到无法识别的选项、无效的数值或参数组合,程序将显示用法错误并退出。因此,如果此方法返回,则表示参数已成功解析。
除了解析命令行参数,在这个函数中还会执行Locks::Init(),如果各种locks没有初始化则会执行初始化。
Profile
LoadInternal函数
-
OpenSource创建/打开文件源 ProfileSource, ProfileSource包含一个fd_和Memmap成员
-
调用ProfileSource::Read读取文件头数据,包括magic、version、section_count
-
获取 section_count
-
调用ProfileSource::Read读取FileSectionInfo, 返回所有 SectionInfo
- 处理强制的 dex 文件区域
- 检查第一个 Section 是否为 kDexFiles
- ReadDexFilesSection
- 遍历接下来的section
- 获取 section_info,不同的类型不同处理
- kExtraDescriptors ReadExtraDescriptorsSection
- kClasses 且 merge_classes标志被设置 ReadClassesSection
- kMethods ReadMethodsSection
- kAggregationCounts 忽略此Section,仅服务器端使用
- default 跳过未知Section,兼容新版本
DoCompilation
sequenceDiagram
participant Caller as Dex2oat函数
participant Dex2Oat as Dex2Oat 对象
participant DexFile
participant CompilerDriver
participant OptimizingCompiler
participant Runtime
Caller->>Dex2Oat: DoCompilation
activate Dex2Oat
Dex2Oat -> DexFile: LoadImageClassDescriptors()
Note right of Dex2Oat: 加载镜像类描述, <br/>如果有Profile,<br/>则只加载DexFile和<br/>ProfileCompilationInfo的交集
DexFile -> DexFile: GetClassDescriptor
Dex2Oat ->> CompilerDriver : Compile()
CompilerDriver -> CompilerDriver : PrepareDexFilesForOatFile
CompilerDriver ->> OptimizingCompiler: CreateOptimizingCompiler
activate OptimizingCompiler
Note over OptimizingCompiler: CompileDexFiles方法
OptimizingCompiler -> Runtime : Runtime::Current()->GetClassLinker()
opt 非bootimage且非bootImageExtension
OptimizingCompiler -> ClassLoaderContext : CreateClassLoader
end
OptimizingCompiler -> OptimizingCompiler : InitializeThreadPools();
OptimizingCompiler -> OptimizingCompiler : PreCompile
OptimizingCompiler -> OptimizingCompiler : CompileAll(class_loader, dex_files, timings_);
OptimizingCompiler -> OptimizingCompiler : FreeThreadPools();
OptimizingCompiler ->> Dex2Oat : 返回 ClassLoader 对象
deactivate OptimizingCompiler
Dex2Oat->>Dex2Oat: WriteOutputFiles()
Note right of Dex2Oat: 将编译结果写入输出文件
Dex2Oat->>Dex2Oat: FlushOutputFiles()
Note right of Dex2Oat: 刷新输出文件,保持打开, 后续可能会剥离符号
opt IsImage()
Note right of Dex2Oat: HandleImage() <br/> 创建 boot.art 并patch oat
Dex2Oat->>Dex2Oat: CreateImageFile()
end
alt IsHost() 不剥离符号快速返回
Dex2Oat->>Dex2Oat: FlushCloseOutputFiles()
Dex2Oat->>Dex2Oat: DumpTiming()
Dex2Oat->>Caller: 返回 kNoFailure
else
Dex2Oat->>Dex2Oat: CopyOatFilesToSymbolsDirectoryAndStrip()
Note right of Dex2Oat: 复制剥离符号的版本到未剥离符号的位置
Dex2Oat->>Dex2Oat: FlushCloseOutputFiles()
Note right of Dex2Oat: 刷新关闭文件
Dex2Oat->>Dex2Oat: DumpTiming()
end
Dex2Oat->>Caller: 返回 kNoFailure
deactivate Dex2Oat
WriteOutputFiles函数
sequenceDiagram
participant Dex2Oat
participant MemMap
Dex2Oat -> MemMap : 遍历每一个opened_dex_files_maps_
MemMap ->> MemMap: Sync() 同步 Dex2Dex 转换后的数据
opt IsImage()
Dex2Oat ->> Dex2Oat: 如果不是boot image 直接设置 image_base_
Dex2Oat ->> ImageWriter: 创建新的 ImageWriter 实例
ImageWriter ->> ImageWriter: PrepareImageAddressSpace() <br/> 为linker patches准备
end
Dex2Oat ->> OatWriter: Initialize(driver, verification_results, image_writer, dex_files)
Note over Dex2Oat: 对于多个Oat文件传入compiler driver, <br/> image writer, dex files初始化OatWriter
opt !use_existing_vdex_
OatWriter->>OatWriter: FinishVdexFile(vdex_file, verifier_deps)
Note over OatWriter: 对于多个Oat/ELF文件生成并写入 VDEX 文件
end
loop 循环处理oat_files_
Dex2Oat -> OatWriter : PrepareLayout准备Oat文件布局
Dex2Oat -> ElfWriter: PrepareDynamicSection准备ELF动态节信息
opt IsImage()
Dex2Oat ->> ImageWriter: UpdateOatFileLayout(...)更新ImageWriter的Oat文件布局信息
end
end
loop 循环处理oat_files_
Dex2Oat->>OatWriter: GetDebugInfo()
Dex2Oat->>ElfWriter: PrepareDebugInfo(debug_info)
Note over ElfWriter: 准备压缩的DebugInfo
Dex2Oat->>OatWriter: WriteRodata(rodata_stream)
Dex2Oat->>ElfWriter: EndRoData(rodata_stream)
Note over ElfWriter: 写入只读数据段 (.rodata)
Dex2Oat->>ElfWriter: StartText()
Dex2Oat->>OatWriter: WriteCode(text_stream)
Dex2Oat->>ElfWriter: EndText(text_stream)
Note over ElfWriter: 写入代码段 (.text)
opt DataImgRelRoSize()
Dex2Oat->>ElfWriter: StartDataImgRelRo()
Dex2Oat->>OatWriter: WriteDataImgRelRo(data_img_rel_ro_stream)
Dex2Oat->>ElfWriter: EndDataImgRelRo(data_img_rel_ro_stream)
Note over ElfWriter: 写入数据镜像相关只读段 (.data.img.rel.ro)
end
Dex2Oat->>OatWriter: WriteHeader(elf_writer->GetStream())
Note over OatWriter: 写入Oat Header
opt IsImage()
Dex2Oat->>ImageWriter: UpdateOatFileHeader(...)
Note over ImageWriter: 更新ImageWriter的Oat文件头信息
end
Dex2Oat->>ElfWriter: WriteDynamicSection()
Note over ElfWriter: 写入ELF动态节
Dex2Oat->>ElfWriter: WriteDebugInfo(oat_writer->GetDebugInfo())
Note over ElfWriter: 写入压缩后的调试信息 (等待压缩任务完成)
Dex2Oat->>ElfWriter: End()
Note over ElfWriter: 结束ELF文件写入
Dex2Oat->>File: FlushOutputFile(&vdex_files_[i])
Dex2Oat->>File: FlushOutputFile(&oat_files_[i])
Note over File: 刷新VDEX和OAT文件
OatWriter->>Dex2Oat: Destroy OatWriter
end
Dex2Oat-->>Dex2Oat: 返回 true