graph TB
Init("init进程通过解析配置脚本")-->|fork子进程运行Zygote服务|AppProcess("/system/bin/app_process:frameworks\base\cmds\app_process\app_main.cc")
AppProcess-->JniInvocation::Init
AppProcess-->AndroidRuntime::StartVm
AppProcess-->C调用Java层ZygoteInit的main方法
zygoteinit.main后续流程参考zygotesource
frameworks\base\cmds\app_process\app_main.cpp
int main(int argc, char* const argv[])
{
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
return 10;
}
void AndroidRuntime::start(const char* className,
const Vector<String8>& options, bool zygote){
......
JniInvocation jni_invocation;
jni_invocation.Init(NULL);//1. 它将加载ART虚拟机的核心动态库。
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote) != 0) { return; }//2. 在ART虚拟机对应的核心动态库加载到zyogte进程后,该函数将启动ART虚拟机。
onVmCreated(env);
......
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
......
char* slashClassName = toSlashClassName(className);//"com.android.internal.os.ZygoteInit"
//找到目标类对应的mirror Class对象
jclass startClass = env->FindClass(slashClassName);//main
if (startClass == NULL) {}
else {
//找到该类中的静态main函数对应的ArtMethod对象
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",//main
"([Ljava/lang/String;)V");
if (startMeth == NULL) {}
else {
//调用这个main函数
env->CallStaticVoidMethod(startClass, startMeth, strArray);//3. main
......
}
}
......
bool JniInvocation::Init(const char* library) {
library = GetLibrary(library, buffer);
const int kDlopenFlags = RTLD_NOW | RTLD_NODELETE;
handle_ = dlopen(library, kDlopenFlags);//动态加载libart.so,main
//初始化三个函数指针,main
if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetDefaultJavaVMInitArgs_),
"JNI_GetDefaultJavaVMInitArgs")) {
return false;
}
if (!FindSymbol(reinterpret_cast<void**>(&JNI_CreateJavaVM_),//赋值创建虚拟机的入口函数,main
"JNI_CreateJavaVM")) {
return false;
}
if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetCreatedJavaVMs_),
"JNI_GetCreatedJavaVMs")) {
return false;
}
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
{
initArgs.version = JNI_VERSION_1_4;
initArgs.options = mOptions.editArray();
initArgs.nOptions = mOptions.size();
initArgs.ignoreUnrecognized = JNI_FALSE;
/*
* Initialize the VM.
*
* The JavaVM* is essentially per-process, and the JNIEnv* is per-thread.
* If this call succeeds, the VM is ready, and we can start issuing
* JNI calls.
*/
if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
ALOGE("JNI_CreateJavaVM failed\n");
return -1;
}
return 0;
extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
return JniInvocation::GetJniInvocation().JNI_CreateJavaVM(p_vm, p_env, vm_args);
}
jint JniInvocation::JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
return JNI_CreateJavaVM_(p_vm, p_env, vm_args);//调用libart.so中的实现
}
java_vm_ext.cc
extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env,void* vm_args) {
ScopedTrace trace(__FUNCTION__);
const JavaVMInitArgs* args = static_cast<JavaVMInitArgs*>(vm_args);
.....//为虚拟机准备参数
bool ignore_unrecognized = args->ignoreUnrecognized;
//①创建Runtime对象,它就是ART虚拟机的化身
if (!Runtime::Create(options, ignore_unrecognized)) {...}
//加载其他关键动态库,它们的文件路径由/etc/public.libraries.txt文件描述
android::InitializeNativeLoader();
Runtime* runtime = Runtime::Current();//获取刚创建的Runtime对象
bool started = runtime->Start();//②启动runtime。注意,这部分内容留待下一章介绍
....
//获取JNI Env和Java VM对象
*p_env = Thread::Current()->GetJniEnv();
*p_vm = runtime->GetJavaVM();
return JNI_OK;
}
runtime.cc
bool Runtime::Create(const RuntimeOptions& raw_options,
bool ignore_unrecognized) {
/*虚拟机是一个复杂系统,所以它有很多控制参数。创建Runtime时,调用者将这些参数信息放在本函数的入参raw_options对象中,该对象的类型是RuntimeOptions。不过,Runtime内部却使用类型为RuntimeArgumentMap的对象来存储参数。下面这段代码中,ParseOptions函数将存储在raw_options里的参数信息提取并保存到runtime_options对象里,而runtime_options的类型就是RuntimeArgumentMap。*/
RuntimeArgumentMap runtime_options;
return ParseOptions(raw_options, ignore_unrecognized, &runtime_options) &&
Create(std::move(runtime_options));
}
bool Runtime::Create(RuntimeArgumentMap&& runtime_options) {
//一个虚拟机进程中只有一个Runtime对象,名为instance_,采用单例方式来创建
if (Runtime::instance_ != nullptr) { return false; }
instance_ = new Runtime; //创建Runtime对象
//用保存了虚拟机控制参数信息的runtime_options来初始化这个runtime对象。
//重点来看Init函数
if (!instance_->Init(std::move(runtime_options))) {....}
return true;
}
bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
RuntimeArgumentMap runtime_options(std::move(runtime_options_in));
//关键模块之MemMap:用于管理内存映射。ART大量使用了内存映射技术。比如.oat文件
//就会通过mmap映射到虚拟机进程的虚拟内存中来。
MemMap::Init();
using Opt = RuntimeArgumentMap;//C++11里using的用法
QuasiAtomic::Startup(); //MIPS架构中需要使用它,其他CPU架构可不考虑
//关键模块之OatFileManager:art虚拟机会打开多个oat文件,通过该模块可统一管理它们
oat_file_manager_ = new OatFileManager;
Thread::SetSensitiveThreadHook(runtime_options.GetOrDefault(
Opt::HookIsSensitiveThread));
//关键模块之Monitor:和Java中的monitor有关,用于实现线程同步的模块。其详情见本书第12章的内容
Monitor::Init(runtime_options.GetOrDefault(Opt::LockProfThreshold));
/*从runtime_options中提取参数。Opt是RuntimeArgumentMap的别名,而BootClassPath是runtime_options.def中定义的一个控制参数的名称。该控制参数的数据类型是vector<unique_ptr<const DexFile>>。从RuntimeArgumentMap中获取一个控制参数的值的函数有两个:
(1)GetOrDefault:从指定参数中获取其值,如果外界没有设置该控制参数,则返回参数配置文件里的配置的默认值。这里的参数配置文件就是上文提到的runtime_options.def。
(2)ReleaseOrDefault:功能和GetOrDefault一样,唯一的区别在于如果外界设置了该参数,该函数将通过std::move函数将参数的值返回给调用者。std move的含义我们在第5章中已做过介绍。使用move的话,外界传入的参数将移动到返回值所在对象里,从而节省了一份内存。比如,假设参数值存储在一个string对象中,如果不使用move的话,那么RuntimeArgumentMap内部将保留一份string,而调用者拿到作为返回值的另外一份string。显然,不使用move的话,将会有两个string对象,内存会浪费一些。所以,ReleaseOrDefault用于获取类类型的控制参数的值,而对于int等基础数据类型,使用GetOrDefault即可。*/
boot_class_path_string_ =
runtime_options.ReleaseOrDefault(Opt::BootClassPath);
......//从runtime_options中获取其他控制参数的值
/*接下来的关键模块为:
(1)MointorList:它维护了一组Monitor对象
(2)MonitorPool:用于创建Monitor对象
(3)ThreadList:用于管理ART中的线程对象(线程对象的数据类型为Thread)的模块
(4)InternTable:该模块和string intern table有关。它其实就是字符串常量池。根据Java语言规范(Java Language Specification,简写为JLS)的要求,内容完全相同的字符串常量(string literal)应该共享同一份资源。比如,假设String a="hello",String b="hello",那么a==b(直接比较对象a是否等于对象b)应该返回true。intern table的目的很好理解,就是减少内存占用。另外,String类中有一个intern方法,它可以将某个String对象添加到intern table中。*/
monitor_list_ = new MonitorList;
monitor_pool_ = MonitorPool::Create();
thread_list_ = new ThreadList;
intern_table_ = new InternTable;
.....//从runtime_options中获取控制参数
//关键模块之Heap:heap是art虚拟机中非常重要的模块。详情见下文分析
heap_ = new gc::Heap(......);
....
//和lambda有关,以后碰见它时再来介绍
lambda_box_table_ = MakeUnique<lambda::BoxTable>();
/*关键模块ArenaPool及LinearAlloc:runtime内部也需要创建很多对象或者需要存储一些信息。为了更好地管理虚拟机自己的内存使用,runtime设计了:
(1)内存池类ArenaPool。ArenaPool可管理多个内存单元(由Arena表示)。
(2)对内存使用者而言,使用内存分配器(LinearAlloc)即可在ArenaPool上分配任意大小的内存。该模块的代码非常简单,请读者自行阅读。*/
const bool use_malloc = IsAotCompiler();
arena_pool_.reset(new ArenaPool(use_malloc, false));
jit_arena_pool_.reset(new ArenaPool(false, false, "CompilerMetadata"));
linear_alloc_.reset(CreateLinearAlloc());
//接下来的一段代码和信号处理有关。ART虚拟机进程需要截获来自操作系统的某些信号
BlockSignals();//阻塞SIGPIPE、SIGQUIT和SIGUSER1信号
/*为某些信号设置自定义的信号处理函数。该函数在linux和android平台上的处理不尽相同。在android(也就是针对设备的编译)平台上,这段代码并未启用。详情可参考该函数在runtime_android.cc中的实现*/
InitPlatformSignalHandlers();
if (!no_sig_chain_) {//对在目标设备上运行的art虚拟机来说,该变量取默认值false
//获取sigaction和sigprocmask两个函数的函数指针。这和linux信号处理
//函数的调用方法有关。此处不拟讨论它,感兴趣的读者可参考代码中的注释
InitializeSignalChain();
/*下面三个变量的介绍如下:
(1)implicit_null_checks_:是否启用隐式空指针检查,此处取值为true。
(2)implict_so_checkes_:是否启用隐式堆栈溢出(stackoverflow)检查,此处取值为true。
(3)implict_suspend_checks_:是否启用隐式线程暂停(thread suspension)检查,此处取值为false。suspend check相关内容将在第11章做详细介绍。*/
if (implicit_null_checks_ || implicit_so_checks_ ||
implicit_suspend_checks_) {
//关键模块之FaultManager:该模块用于处理SIGSEV信号
fault_manager.Init();
/*下面的SuspensionHandler、StackOverflowHandler和NullPointerHandler有共同的基类FaultHandler,笔者将它们归为关键模块FaultManager之中。这部分内容 留待下文再介绍*/
if (implicit_suspend_checks_) {
new SuspensionHandler(&fault_manager);
}
if (implicit_so_checks_) {
new StackOverflowHandler(&fault_manager);
}
if (implicit_null_checks_) {
new NullPointerHandler(&fault_manager);
}
..... }
}
/*关键模块之JavaVmExt:JavaVmExt就是JNI中代表Java虚拟机的对象,其基类为JavaVM,真实类型为JavaVmExt。根据JNI规范,一个进程只有唯一的一个JavaVm对象。对art虚拟机来说,这个JavaVm对象就是此处的java_vm_。*/
java_vm_ = new JavaVMExt(this, runtime_options);
//关键模块之Thread:Thread是虚拟机中代表线程的类,下面两个函数调用Thread类的
//Startup和Attach以初始化虚拟机主线程
Thread::Startup();
Thread* self = Thread::Attach("main", false, nullptr, false);
self->TransitionFromSuspendedToRunnable();
//关键模块之ClassLinker:ClassLinker也是非常重要的模块。从其命名可以看出,它处理
//和Class有关的工作,比如解析某个类、寻找某个类等
class_linker_ = new ClassLinker(intern_table_);
if (GetHeap()->HasBootImageSpace()) {
std::string error_msg;
//从oat镜像文件中初始化class linker,也就是从oat文件中获取类等信息。
bool result = class_linker_->InitFromBootImage(&error_msg);
{
ScopedTrace trace2("AddImageStringsToTable");
//处理和intern table有关的初始化
GetInternTable()->AddImagesStringsToTable(heap_->GetBootImageSpaces());
}
{
ScopedTrace trace2("MoveImageClassesToClassTable");
//art虚拟机中每一个class loader都有一个class table,它存储了该loader
//所加载的各种class。下面这个函数将把来自镜像中的类信息添加到boot class loader
//对应的ClassTable中。这部分内容将在ClassLinker一节中介绍
GetClassLinker()->AddBootImageClassesToClassTable();
}
}
......
//关键模块之MethodVerifier:用于校验Java方法的模块。下一章介绍类校验方面知识时
//将接触MethodVerifier类。本书不拟对该类做过多介绍。
verifier::MethodVerifier::Init();
/*下面这段代码用于创建两个异常对象。注意,此处ThrowNewException将创建异常对象,而ClearException将清除异常对象。这样的话,Init函数返回后将不会导致异常投递。这是JNI函数中常用的做法。读者可以先不用了解这么多,后续章节介绍JNI及异常投递时还会详细介绍。
pre_allocated_OutOfMemoryError_和pre_allocated_NoClassDefFoundError_代表Java层OutOfMemoryError对象和NoClassDefFoundError对象。*/
self->ThrowNewException("Ljava/lang/OutOfMemoryError;",....);
pre_allocated_OutOfMemoryError_ = GcRoot<mirror::Throwable>(self->GetException());
self->ClearException();
self->ThrowNewException("Ljava/lang/NoClassDefFoundError;",...);
pre_allocated_NoClassDefFoundError_ = GcRoot<mirror::Throwable>(self->GetException());
self->ClearException();
......//native bridge library加载,本文不涉及相关内容
return true;
}
MemMap
static MemMap* MapAnonymous(const char* name, uint8_t* addr,
size_t byte_count, int prot, bool low_4gb, bool reuse,
std::string* error_msg, bool use_ashmem = true);
static MemMap* MapFile(size_t byte_count,int prot, int flags, int fd,off_t start, bool low_4gb, const char* filename, std::string* error_msg) {
return MapFileAtAddress(nullptr,....);//最终调用这个函数完成内存映射
}
static MemMap* MapFileAtAddress(uint8_t* addr, size_t byte_count, .....std::string* error_msg);
static Maps* maps_ GUARDED_BY(Locks::mem_maps_lock_);
MemMap(const std::string& name,uint8_t* begin,size_t size,
void* base_begin,size_t base_size,int prot,
bool reuse,size_t redzone_size = 0) REQUIRES(!Locks::mem_maps_lock_);
//该函数内部将调用mmap来完成实际的内存映射操作,读者可自行查看其代码
static void* MapInternal(void* addr, size_t length,int prot, int flags,int fd, off_t offset, bool low_4gb);
.....;
};
void MemMap::Init() {
MutexLock mu(Thread::Current(), *Locks::mem_maps_lock_);
if (maps_ == nullptr) {//Init中使用了mem_maps_lock_锁
maps_ = new Maps;
}
}
static jclass FindClass(JNIEnv* env, const char* name) {
CHECK_NON_NULL_ARGUMENT(name);
Runtime* runtime = Runtime::Current();
ClassLinker* class_linker = runtime->GetClassLinker();
std::string descriptor(NormalizeJniClassDescriptor(name));
ScopedObjectAccess soa(env);
mirror::Class* c = nullptr;
if (runtime->IsStarted()) {
StackHandleScope<1> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(GetClassLoader(soa)));
c = class_linker->FindClass(soa.Self(), descriptor.c_str(), class_loader);//main
} else {
c = class_linker->FindSystemClass(soa.Self(), descriptor.c_str());
}
return soa.AddLocalReference<jclass>(c);
}
static jmethodID GetStaticMethodID(JNIEnv* env, jclass java_class, const char* name,
const char* sig) {
CHECK_NON_NULL_ARGUMENT(java_class);
CHECK_NON_NULL_ARGUMENT(name);
CHECK_NON_NULL_ARGUMENT(sig);
ScopedObjectAccess soa(env);
return FindMethodID(soa, java_class, name, sig, true);
}
static jmethodID FindMethodID(ScopedObjectAccess& soa, jclass jni_class,
const char* name, const char* sig, bool is_static)
SHARED_REQUIRES(Locks::mutator_lock_) {
mirror::Class* c = EnsureInitialized(soa.Self(), soa.Decode<mirror::Class*>(jni_class));
if (c == nullptr) {
return nullptr;
}
ArtMethod* method = nullptr;
auto pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
if (is_static) {
method = c->FindDirectMethod(name, sig, pointer_size);
} else if (c->IsInterface()) {
method = c->FindInterfaceMethod(name, sig, pointer_size);
} else {
method = c->FindVirtualMethod(name, sig, pointer_size);
if (method == nullptr) {
// No virtual method matching the signature. Search declared
// private methods and constructors.
method = c->FindDeclaredDirectMethod(name, sig, pointer_size);
}
}
......
return soa.EncodeMethod(method);
}
static void CallStaticVoidMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
va_list ap;
va_start(ap, mid);
CHECK_NON_NULL_ARGUMENT_RETURN_VOID(mid);
ScopedObjectAccess soa(env);
InvokeWithVarArgs(soa, nullptr, mid, ap);
va_end(ap);
}
static jobject CallStaticObjectMethod(JNIEnv* env, jclass,
jmethodID mid, ...) {
va_list ap;
va_start(ap, mid);
ScopedObjectAccess soa(env);
//先调用InvokeWithVarArgs,返回值存储在result中
JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap));
jobject local_result = soa.AddLocalReference<jobject>(result.GetL());
va_end(ap);
return local_result;
}
JValue InvokeWithVarArgs(const ScopedObjectAccessAlreadyRunnable& soa,
jobject obj, jmethodID mid, va_list args) {
.....
ArtMethod* method = soa.DecodeMethod(mid);
bool is_string_init = .....;
if (is_string_init) {......}
mirror::Object* receiver = method->IsStatic() ? nullptr :
soa.Decode<mirror::Object*>(obj);
uint32_t shorty_len = 0;
const char* shorty = method->GetInterfaceMethodIfProxy(
sizeof(void*))->GetShorty(&shorty_len);
JValue result;
ArgArray arg_array(shorty, shorty_len);
arg_array.BuildArgArrayFromVarArgs(soa, receiver, args);
//调用InvokeWithArgArray
InvokeWithArgArray(soa, method, &arg_array, &result, shorty);
.....
return result;
}
static void InvokeWithArgArray(const ScopedObjectAccessAlreadyRunnable& soa,
ArtMethod* method, ArgArray* arg_array, JValue* result,
const char* shorty) {
uint32_t* args = arg_array->GetArray();
......
//调用ArtMethod的Invoke函数
method->Invoke(soa.Self(), args, arg_array->GetNumBytes(),
result, shorty);
}