Android Dalvik虚拟机 启动和初始化
Posted baiiu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Dalvik虚拟机 启动和初始化相关的知识,希望对你有一定的参考价值。
前言
最近因工作需要,阅读了一些Dalvik虚拟机代码,整理输出一波。本文整理Dalvik虚拟机在启动流程和初始化流程,为下篇分析Dalvik的内存分配流程和gc流程打一个基础。
本系列代码均基于4.4.2分析。
Dalvik虚拟机启动流程
AndroidRuntime.cpp
/*
* Start the Dalvik Virtual Machine.
*
* Various arguments, most determined by system properties, are passed in.
* The "mOptions" vector is updated.
*
* Returns 0 on success.
*/
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
// 拼接一大堆虚拟机初始化参数
// adb shell getprop | grep dalvik 通过该命令可以查看一些
/*
* 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");
goto bail;
result = 0;
bail:
free(stackTraceFile);
return result;
Jni.cpp
/*
* Create a new VM instance.
*
* The current thread becomes the main VM thread. We return immediately,
* which effectively means the caller is executing in a native method.
*/
jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args)
// 初始化gDvm全局变量
memset(&gDvm, 0, sizeof(gDvm));
// 初始化JavaVmExt
JavaVMExt* pVM = (JavaVMExt*) calloc(1, sizeof(JavaVMExt));
pVM->funcTable = &gInvokeInterface; // jni表
// Create a JNIEnv for the main thread.
JNIEnvExt* pEnv = (JNIEnvExt*) dvmCreateJNIEnv(NULL);
// 启动虚拟机
dvmStartup(argc, argv.get(), args->ignoreUnrecognized, (JNIEnv*)pEnv);
return JNI_OK;
init.cpp
在init.cpp中做Dalvik虚拟机初始化操作。
/*
* VM initialization. Pass in any options provided on the command line.
* Do not pass in the class name or the options for the class.
*
* Returns 0 on success.
*/
std::string dvmStartup(int argc, const char* const argv[], bool ignoreUnrecognized, JNIEnv* pEnv)
/*
* Initialize components.
*/
// 初始化Davlik的内存分配记录模块AllocTracker。
dvmAllocTrackerStartup();
// 初始化Dalvik的垃圾回收模块。内部包含堆初始化
dvmGcStartup();
// 初始化Davlik的线程管理模块。Dalvik线程就是Linux的线程,线程管理模块只是用Thread类来记录Dalvik与线程相关的数据。所有Thread类会形成一个链表。这里除了初始化链表外,还会为主线程创建一个Thread类,并把它加入到链表中。
dvmThreadStartup();
// 初始化Davlik的内部native函数模块
dvmInlineNativeStartup();
// 初始化Dalvik的寄存器映射模块Register Map
dvmRegisterMapStartup();
// 初始化Dalvik的instanceof操作符缓存模块
dvmInstanceofStartup();
// 初始化Dalvik的类装载模块,类装载模块主要负责装载和查找Java类
dvmClassStartup();
// 初始化gDvm中定义的所有Java关键字的类
dvmFindRequiredClassesAndMembers()
// 初始化Dalvik的常量字符串模块。Dalvik在装载类时,会把类中定义的各种字符串都放入gDvm的两个hash表internedStrings和literalStrings中。Dalvik内部创建相同字符串的对象时只会产生引用而不再创建对象了,这样就能节约重复字符串占用的内存。
dvmStringInternStartup();
// 初始化Dalvik的native函数管理模块
dvmNativeStartup();
// 初始化Dalvik内部类的native函数模块。这个模块定义了所有Dalvik的内部类的native函数表。如DexFile、VMRuntime、DexFile等
dvmInternalNativeStartup();
// 初始化Dalvik的JNI模块。主要是创建了全局引用表和全局弱引用表
dvmJniStartup();
// 这个函数的作用是初始化类java.lang.Class
dvmInitClass();
// 注册com.android.dex.Dex的native方法getDex()。同时装载JNI库libjavacore.so以及libnativehelper.so
registerSystemNatives();
// 。创建一些异常对象,包括OutOfMemoryError、InternalError和NoClassDefFoundError,保存在gDvm中
dvmCreateStockExceptions();
// 执行java.lang.Daemons的start()方法来启动和初始化垃圾回收线程
dvmGcStartupClasses();
// 虚拟机OK了,zygote再继续启动
initZygote();
重要变量gDvm
在dalvik/vm/Globals.h头文件中定义,里面参数太多了,列出了如下一般开发涉及的重要变量。
这种变量是全局变量,可以通过dlsys获取到,再获取其内部的参数,在hook时经常用到。
/* global state */
struct DvmGlobals gDvm;
/*
* All fields are initialized to zero.
*
* Storage allocated here must be freed by a subsystem shutdown function.
*/
struct DvmGlobals
// 几个最基本的jar包的路径。包括core.jar、ext.jar、framework,jar、services.jar和android.policy.jar
char* bootClassPathStr;
// 存放系统jar包的路径。通常为/system/framework
char* classPathStr;
// 堆初始化参数,下篇再讲
size_t heapStartingSize;
size_t heapMaximumSize;
size_t heapGrowthLimit;
bool lowMemoryMode;
double heapTargetUtilization;
size_t heapMinFree;
size_t heapMaxFree;
size_t stackSize;
size_t mainThreadStackSize;
/*
* Loaded classes, hashed by class name. Each entry is a ClassObject*,
* allocated in GC space.
*/
HashTable* loadedClasses;
/* Hash table of strings interned by the user. */
HashTable* internedStrings;
/* Hash table of strings interned by the class loader. */
HashTable* literalStrings;
/*
* Thread list. This always has at least one element in it (main),
* and main is always the first entry.
*/
Thread* threadList;
/*
* JNI global reference table.
*/
IndirectRefTable jniGlobalRefTable;
IndirectRefTable jniWeakGlobalRefTable;
pthread_mutex_t jniGlobalRefLock;
pthread_mutex_t jniWeakGlobalRefLock;
/*
* Native shared library table.
*/
HashTable* nativeLibs;
/*
* GC heap lock. Functions like gcMalloc() acquire this before making
* any changes to the heap. It is held throughout garbage collection.
*/
pthread_mutex_t gcHeapLock;
/*
* Condition variable to queue threads waiting to retry an
* allocation. Signaled after a concurrent GC is completed.
*/
pthread_cond_t gcHeapCond;
/* Opaque pointer representing the heap. */
GcHeap* gcHeap;
/* Monitor list, so we can free them */
/*volatile*/ Monitor* monitorList;
extern struct DvmGlobals gDvm;
以上是关于Android Dalvik虚拟机 启动和初始化的主要内容,如果未能解决你的问题,请参考以下文章