从Dalvik findClass方面看,又可把Java类分为System Class与非System Class。System Class一般指的是Java的类库和Andrioid的核心类。而它们的区别在于,System Class是由虚拟机初始化时候加载的。而因为Android的Kernel是基于Linux Kernel,Android在创建一个新的进程时,设计了Zygote这个特殊的进程来fork新的进程,因为fork的写时复制特性,而每一次都是基于Zygote这个进程来fork的,因此,每一个新的进程诞生不仅拥有了一个自己的dalvik,而且这个dalvik基本上是一个只是加载了system class的dalvik。而后,随着程序的运行,每个虚拟才有了彼此的不同,加载着各个进程的class及其他资源。
Android的Zygote进程的bin档就是system\bin\app_process,在app_process进程的main()函数中,随着startVM()的调用,就标示着Dalvik的启动。在startVM()中,通过property_get()调用,初始化Dalvik的基本配置信息,如初始堆,最大可用堆的大小,是否支持JIT,选择什么模式的解释器等。例如以下代码就是对解释器的选择。
property_get("dalvik.vm.execution-mode", propBuf, ""); if (strcmp(propBuf, "int:portable") == 0) { executionMode = kEMIntPortable; } else if (strcmp(propBuf, "int:fast") == 0) { executionMode = kEMIntFast; #if defined(WITH_JIT) } else if (strcmp(propBuf, "int:jit") == 0) { executionMode = kEMJitCompiler; #endif }
设置好了基本的配置属性后,就会利用这些属性,通过JNI_CreateJavaVM()的调用创建虚拟机,为什么CreateJavaVM前面要加个JNI_前缘呢,好像挺奇怪的,它并不是jni函数啊。而然后经过dvmStartup()的调用,会初始化GC内存管理及一部分系统类。初始化这部分系统类,调用的是dvmClassStartup()。那么,这部分系统类是什么呢,为什么要单独放出来呢?
在dvmClassStartup()中,第一步并不是急着去加载类,而是初始化一个HashMap表,用以保存所有被该虚拟机所加载的类。HashMap创建好之后就会被保存在gDVM中。gDVM是一个全局变量,它的类型是DvmGlobals,这是个C++ struct类型,成员变量相当的多,其中不仅保存着已加载的类,还保存着Dalvik实例。
struct DvmGlobals gDvm; gDvm.loadedClasses = dvmHashTableCreate(256, (HashFreeFunc) dvmFreeClassInnards);
接下来,就是调用createInitialClasses()来加载这部分系统类了。
/* * Create the initial classes. These are the first objects constructed * within the nascent VM. */ if (!createInitialClasses()) { return false; }
从代码的实现来看,这里分为两部分工作,第一部分为加载Java中最为神秘的类Class,第二部分就是加载了用于构造Java这门语言的基础类型,有了它,才能定义我们所说的类。
/* * Create the initial class instances. These consist of the class * Class and all of the classes representing primitive types. */ static bool createInitialClasses() { /* * Initialize the class Class. This has to be done specially, particularly * because it is an instance of itself. */ // 初始化Class ClassObject* clazz = (ClassObject*) dvmMalloc(classObjectSize(CLASS_SFIELD_SLOTS), ALLOC_NON_MOVING); if (clazz == NULL) { return false; } DVM_OBJECT_INIT(clazz, clazz); SET_CLASS_FLAG(clazz, ACC_PUBLIC | ACC_FINAL | CLASS_ISCLASS); clazz->descriptor = "Ljava/lang/Class;"; gDvm.classJavaLangClass = clazz; LOGVV("Constructed the class Class."); /* * Initialize the classes representing primitive types. These are * instances of the class Class, but other than that they're fairly * different from regular classes. */ // 初始化基本类型 bool ok = true; ok &= createPrimitiveType(PRIM_VOID, &gDvm.typeVoid); ok &= createPrimitiveType(PRIM_BOOLEAN, &gDvm.typeBoolean); ok &= createPrimitiveType(PRIM_BYTE, &gDvm.typeByte); ok &= createPrimitiveType(PRIM_SHORT, &gDvm.typeShort); ok &= createPrimitiveType(PRIM_CHAR, &gDvm.typeChar); ok &= createPrimitiveType(PRIM_INT, &gDvm.typeInt); ok &= createPrimitiveType(PRIM_LONG, &gDvm.typeLong); ok &= createPrimitiveType(PRIM_FLOAT, &gDvm.typeFloat); ok &= createPrimitiveType(PRIM_DOUBLE, &gDvm.typeDouble); return ok; }