浅析ART虚拟机(一)虚拟机第一次启动

浅析ART虚拟机(一)虚拟机第一次启动

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& 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(&JNI_GetDefaultJavaVMInitArgs_),

"JNI_GetDefaultJavaVMInitArgs")) {

return false;

}

if (!FindSymbol(reinterpret_cast(&JNI_CreateJavaVM_),

"JNI_CreateJavaVM")) {

return false;

}

if (!FindSymbol(reinterpret_cast(&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函数。

相关发现

什么是WSS协议?
best365官网登录入口

什么是WSS协议?

🌼 07-02 🌻 9116
【基础篇】Java关键字(超详细)
365bet体育手机

【基础篇】Java关键字(超详细)

🌼 07-03 🌻 3282
新公司做账全过程
best365官网登录入口

新公司做账全过程

🌼 07-09 🌻 4459
凯恩戴帽 英格兰6
365BET是不是上市了

凯恩戴帽 英格兰6

🌼 06-29 🌻 1425