Android Java虚拟机创建过程

本文基于Android8.0源码

Android8.0使用的java虚拟机为ART,在大名鼎鼎的zygote进程中启动java虚拟机。
首先看一下zygote的main函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//app_main.cpp
int main(int argc, char* const argv[])
{
//AppRuntime继承自AndroidRuntime, 构造函数中没有什么有用信息,可以不关注
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
//...
if (zygote) {
//调用到AndroidRuntime.start函数启动zygote进程的虚拟机
//传入的第一个参数是java类ZygoteInit
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.");
}
}

runtime.start会调用父类的AndroidRuntime::start,看一下实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//AndroidRuntime.cpp

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
......
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL); // 1. 加载虚拟机动态库,并加载库函数符号
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote) != 0) { // 2. 启动虚拟机
return;
}
onVmCreated(env);

/*
* Register android functions.
*/
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
......

if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
//调用com.android.internal.os.ZygoteInit的main函数,从此便进入了Java的世界
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
env->CallStaticVoidMethod(startClass, startMeth, strArray);
}
}
}
  1. 加载虚拟机动态库,并加载库函数符号
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//JniInvocation.cpp

bool JniInvocation::Init(const char* library) {
......
library = GetLibrary(library, buffer); //返回“libart.so” art虚拟机库
......
handle_ = dlopen(library, kDlopenFlags); //动态加载虚拟机so库
......
//下面的三个if语句都是通过dlsym来获取虚拟机so库中的函数符号
if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetDefaultJavaVMInitArgs_),
"JNI_GetDefaultJavaVMInitArgs")) {
return false;
}
//无比重要的函数,获取虚拟机构造函数的函数符号,创建虚拟机全靠JNI_CreateJavaVM
if (!FindSymbol(reinterpret_cast<void**>(&JNI_CreateJavaVM_),
"JNI_CreateJavaVM")) {
return false;
}
if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetCreatedJavaVMs_),
"JNI_GetCreatedJavaVMs")) {
return false;
}
return true;
}
jint JniInvocation::JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
return JNI_CreateJavaVM_(p_vm, p_env, vm_args);
}

//该函数就是最终创建虚拟机的函数
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);
}
  1. 启动虚拟机
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
* Start the Dalvik Virtual Machine.
*/
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
{
...... //组装虚拟机启动参数
/*
* 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;
}