1.前言:
ART是Android上的应用和部分系统服务使用的托管式运行时,ART和前身Dalvik最初是专为Android项目打造的。 每一个APP进程中都有一个ART的虚拟机副本,这些副本都是从zygote中复制过来的,虽然都有,但是对应到实际的物理内存中只存在了一份,这也解释了为什么APP进程的启动为什么需要zygote的copy on write机制。
2.第一个ART虚拟机启动
内核启动后到达用户空间,第一个进程init通过读取init.rc来进行Android世界的初始化,孵化出Android世界的第一个进程zygote,而在zygote中,就初始化了第一个ART虚拟机。
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
class main
priority -20
user root
group root readproc reserved_disk
socket zygote stream 660 root system
socket usap_pool_primary stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
onrestart restart vendor.servicetracker-1-1
writepid /dev/cpuset/foreground/tasks
对应的源文件就是App_main.cpp,进程名为zygote。
3.zygote中启动ART虚拟机
3.1App_main中
int main(int argc, char* const argv[])
{
AppRuntime runtime(argv[0], computeArgBlockSize(argc, 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.");
}
}
3.2 AppRuntime->start()既AndroidRuntime->start()
因为AppRuntime继承AndroidRuntime,从注释也可以看到,在创建了虚拟机之后,会调用传过来的zygoteInit.main方法。
/*
* Start the Android runtime. This involves starting the virtual machine
* and calling the "static void main(String[] args)" method in the class
* named by "className".
*
* Passes the main function two arguments, the class name and the specified
* options string.
*/
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
// className = com.android.internal.os.ZygoteInit
...
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL); //见3.3
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote) != 0) { // 见3.4
return;
}
onVmCreated(env);
...
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
// 调用com.android.internal.os.ZygoteInit的main方法
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);
#if 0
if (env->ExceptionCheck())
threadExitUncaughtException(env);
#endif
}
}
}
3.3 jni_invocation.Init(NULL);
虚拟机启动部分,首先进行了init。主要就是确认了虚拟机的3个重要的函数,确认了入口。
bool JniInvocationImpl::Init(const char* library) {
library = GetLibrary(library, buffer);
...
if (!FindSymbol(reinterpret_cast<FUNC_POINTER*>(&JNI_GetDefaultJavaVMInitArgs_),
"JNI_GetDefaultJavaVMInitArgs")) {
return false;
}
if (!FindSymbol(reinterpret_cast<FUNC_POINTER*>(&JNI_CreateJavaVM_),
"JNI_CreateJavaVM")) {
return false;
}
if (!FindSymbol(reinterpret_cast<FUNC_POINTER*>(&JNI_GetCreatedJavaVMs_),
"JNI_GetCreatedJavaVMs")) {
return false;
}
}
其中的getLibrary也就是
static const char* kLibraryFallback = "libart.so";
也就是我们可以通过配置属性来决定当前使用的虚拟机,目前我们使用的也就是art虚拟机了。好的,现在init完成了,让我们回到启动虚拟机.
3.4 startVM()
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;
}
}
3.5 JNI_CreateJavaVM
jint JniInvocationImpl::JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
return JNI_CreateJavaVM_(p_vm, p_env, vm_args);
}
而此处的JNI_CreateJavaVM_就是在3.3中保存在变量中的入口。也就是libart.so中的JNI_CreateJavaVM函数。