本文基于Android 7.1,不过因为从BSP拿到的版本略有区别,所以本文提到的源码未必与读者找到的源码完全一致。本文在提供源码片断时,将按照 <源码相对android工程的路径>:<行号> <类名> <函数名> 的方式,如果行号对不上,请参考类名和函数名来找到对应的源码。
RuntimeOptions到RuntimeArgumentMap
在JNI_CreateJavaVM函数中,JavaVMOption对象被转换为RuntimeOptions对象。
RuntimeOptions实际上只是一个vector定义:
art/runtime/parsed_options.h:38
typedef std::vector<std::pair<std::string, const void*>> RuntimeOptions;
内部的parie对象,第一个参数保存的是放进去的字符串数据,第二个是附加参数。一般附加参数不用。
for (int i = 0; i < args->nOptions; ++i) {
JavaVMOption* option = &args->options[i];
options.push_back(std::make_pair(std::string(option->optionString), option->extraInfo));
}
当数据填充完成后,调用Runtime::Create方法,传递给Runtime,用于创建Runtime。
art/runtime/runtime.cc:486 Runtime::Create
bool Runtime::Create(const RuntimeOptions& raw_options, bool ignore_unrecognized) {
RuntimeArgumentMap runtime_options;
return ParseOptions(raw_options, ignore_unrecognized, &runtime_options) &&
Create(std::move(runtime_options));
}
注意到return语句,先调用ParseOptions, 将RuntimeOptions转换为RuntimeArugmentMap。
本章要重点分析的就是这个ParseOptions函数。
首先看看RuntimeArugmentMap是什么结构。
Runtime::ParseOptions
该函数解析参数的入口。Runtime::ParseOptions调用 ParsedOptions:Parse函数,再调用 ParsedOptions::DoParse函数。
DoParse函数,主体有两个函数:MakeParse和RuntimeParser::Parse函数。
首先,看看MakeParse函数。
MakeParse函数
这个函数用了非常复杂的C++模板,生成一个解析数据结构。因为内容太多,我摘录了关键部分,进行解说。
请先看下面的代码
runtime/parsed_options.cc:61 ParsedOptions::MakeParser
std::unique_ptr<RuntimeParser> ParsedOptions::MakeParser(bool ignore_unrecognized) {
using M = RuntimeArgumentMap;
std::unique_ptr<RuntimeParser::Builder> parser_builder =
std::unique_ptr<RuntimeParser::Builder>(new RuntimeParser::Builder());
parser_builder->
Define("-Xzygote")
.IntoKey(M::Zygote)
.Define("-help")
.IntoKey(M::Help)
.....
.WithType<ParseStringList<':'>>() // std::vector<std::string>, split by :
.IntoKey(M::BootClassPathLocations)
.Define({"-classpath _", "-cp _"})
.WithType<std::string>()
.IntoKey(M::ClassPath)
.Define("-Ximage:_")
.WithType<std::string>()
.IntoKey(M::Image)
....
.Define("-D_")
.WithType<std::vector<std::string>>().AppendValues()
.IntoKey(M::PropertiesList)
....
.Define({"-XX:EnableHSpaceCompactForOOM", "-XX:DisableHSpaceCompactForOOM"})
.WithValues({true, false})
.IntoKey(M::EnableHSpaceCompactForOOM)
....
.Define("-XX:HeapTargetUtilization=_")
.WithType<double>().WithRange(0.1, 0.9)
....
.Define("-Xint")
.WithValue(true)
.IntoKey(M::Interpret)
....
.Define("-Xmx_")
.WithType<MemoryKiB>()
.IntoKey(M::MemoryMaximumSize)
.....
.Define("-XX:DumpNativeStackOnSigQuit:_")
.WithType<bool>()
.WithValueMap({
{"false", false}, {"true", true}})
.IntoKey(M::DumpNativeStackOnSigQuit)
.....
.Define("-XX:LargeObjectSpace=_")
.WithType<gc::space::LargeObjectSpaceType>()
.WithValueMap({
{"disabled", gc::space::LargeObjectSpaceType::kDisabled},
{"freelist", gc::space::LargeObjectSpaceType::kFreeList},
{"map", gc::space::LargeObjectSpaceType::kMap}})
.IntoKey(M::La