java VM
1. -Xcheck:jni:用来启动JNI方法检查。我们在C/C++代码中,可以修改Java对象的成员变量或者调用Java对象的成员函数。加了-Xcheck:jni选项之后,就可以对要访问的Java对象的成员变量或者成员函数进行合法性检查,例如,检查类型是否匹配。我们可以通过dalvik.vm.checkjni或者ro.kernel.android.checkjni这两个系统属性来指定是否要启用-Xcheck:jni选项。注意,加了-Xcheck:jni选项之后,会使用得JNI方法执行变慢。
2. -Xint:portable,-Xint:fast,-Xint:jit:用来指定Dalvik虚拟机的执行模式。Dalvik虚拟机支持三种运行模式,分别是Portable、Fast和Jit。Portable是指Dalvik虚拟机以可移植的方式来进行编译,也就是说,编译出来的虚拟机可以在任意平台上运行。Fast是针对当前平台对Dalvik虚拟机进行编译,这样编译出来的Dalvik虚拟机可以进行特殊的优化,从而使得它能更快地运行程序。Jit不是解释执行代码,而是将代码动态编译成本地语言后再执行。我们可以通过dalvik.vm.execution-mode系统属笥来指定Dalvik虚拟机的解释模式。
3. -Xstacktracefile:用来指定调用堆栈输出文件。Dalvik虚拟机接收到SIGQUIT(Ctrl-\或者kill -3)信号之后,会将所有线程的调用堆栈输出来,默认是输出到日志里面。指定了-Xstacktracefile选项之后,就可以将线程的调用堆栈输出到指定的文件中去。我们可以通过dalvik.vm.stack-trace-file系统属性来指定调用堆栈输出文件。
4. -Xmx:用来指定Java对象堆的最大值。Dalvik虚拟机的Java对象堆的默认最大值是16M,不过我们可以通过dalvik.vm.heapsize系统属性来指定为其它值。
每一个Dalvik虚拟机实例都有一个函数表,保存在对应的JavaVMExt对象的成员变量funcTable中,而这个函数表又被指定为gInvokeInterface。gInvokeInterface是一个类型为JNIInvokeInterface的结构体
有了这个Dalvik虚拟机函数表之后,我们就可以将当前线程Attach或者Detach到Dalvik虚拟机中去,或者销毁当前进程的Dalvik虚拟机等。
每一个Dalvik虚拟机实例还有一个JNI环境列表,保存在对应的JavaVMExt对象的成员变量envList中。注意,JavaVMExt对象的成员变量envList描述的是一个JNIEnvExt列表,其中,每一个Attach到Dalvik虚拟机中去的线程都有一个对应的JNIEnvExt,用来描述它的JNI环境。有了这个JNI环境之后,我们才可以在Java函数和C/C++函数之间互相调用。
每一个JNIEnvExt对象都有两个成员变量prev和next,它们均是一个JNIEnvExt指针,分别指向前一个JNIEnvExt对象和后一个JNIEnvExt对象,也就是说,每一个Dalvik虚拟机实例的成员变量envList描述的是一个双向JNIEnvExt列表,其中,列表中的第一个JNIEnvExt对象描述的是主线程的JNI环境。
如果我们没有在Dalvik虚拟机的启动选项中指定-Xrs,那么gDvm.reduceSignals的值就会被设置为false,表示要在当前线程中屏蔽掉SIGQUIT信号。在这种情况下,会有一个线程专门用来处理SIGQUIT信号。这个线程在接收到SIGQUIT信号的时候,就会将各个线程的调用堆栈打印出来,因此,这个线程又称为dump-stack-trace线程。
屏蔽当前线程的SIGQUIT信号是通过调用函数blockSignals来实现的,这个函数定义在文件dalvik/vm/Init.c中。
Runtime类的成员函数GetHeap返回的便是当前ART虚拟机的堆,也就是前面创建的ART虚拟机堆。通过调用Heap类的成员函数GetContinuousSpaces可以获得堆里面的连续空间列表。如果这个列表的第一个连续空间是一个Image空间,那么就调用ClassLinker类的静态成员函数CreateFromImage来创建一个ClassLinker对象。否则的话,上述ClassLinker对象就要通过ClassLinker类的另外一个静态成员函数CreateFromCompiler来创建。创建出来的ClassLinker对象是后面ART虚拟机加载加载Java类时要用到的。
后面我们分析ART虚拟机的垃圾收集机制时会看到,ART虚拟机的堆包含有三个连续空间和一个不连续空间。三个连续空间分别用来分配不同的对象。当第一个连续空间不是Image空间时,就表明当前进程不是Zygote进程,而是安装应用程序时启动的一个dex2oat进程。安装应用程序时启动的dex2oat进程也会在内部创建一个ART虚拟机,不过这个ART虚拟机是用来将DEX字节码编译成本地机器指令的,而Zygote进程创建的ART虚拟机是用来运行应用程序的。
参数original_image_file_name描述的就是前面提到的Image文件的路径。如果它的值不等于空的话,那么就以它为参数,调用ImageSpace类的静态成员函数Create创建一个Image空间,并且调用Heap类的成员函数AddContinuousSpace将该Image空间作为本进程的ART虚拟机堆的第一个连续空间。
std::string GetSystemImageFilename(const char* location, const InstructionSet isa) { // location = /system/framework/boot.art // filename = /system/framework/<isa>/boot.art std::string filename(location); InsertIsaDirectory(isa, &filename); return filename; }

浙公网安备 33010602011771号