分类: Java
2008-11-24 00:52:23
JAVA虚拟机
1. 生命周期
一个运行时JAVA虚拟机实例的职责就是负责运行一个JAVA程序。
当启动一个JAVA程序时,一个JAVA虚拟机实例就诞生了。
当程序关闭时,这个虚拟机实例也随之消亡。
每个JAVA程序都运行与它自己的虚拟机实例中。
Phoneme里有SVM和MVM模式,SVM表示同时只能运行一个JAVA虚拟机实例,而MVM表示可以同时运行多个虚拟机实例。
MAX_ISOLATES,一个ISOLATE代表什么?允许同时运行的虚拟机实例的个数?虚拟机内部创建的线程个数?
JAVA虚拟机实例通过调用某个初始类的main函数,这个main方法必须是public,static,返回void,并且接受一个字符串数组作为参数。必须告知JAVA虚拟机要运行的JAVA程序中初始类的名字。Main方法作为改程序初始线程的起点,任何其他线程通常都是由虚拟机自己使用的。
phoneme通过midpRunVm(Midp_master_mode_events.c)启动一个虚拟机实例。
int midpRunVm(JvmPathChar* classPath,char* mainClass,int argc, char** argv)
调用midpRunVm启动一个虚拟机实例,在程序未退出之前,midpRunVm不会返回。
(runNams.c)
1. runMidletWithNAMS
setupArgToStartMidlet->set classNameToRun(static)
midp_system_start->
vmStatus = midpRunMainClass(NULL, APP_MANAGER_PEER, 0, NULL);
#define APP_MANAGER_PEER "com.sun.midp.main.NativeAppManagerPeer"
vmStatus = midpRunVm(classPath, mainClass, argc, argv);->
JVM_Start(classPath, mainClass, argc, argv);
分析:
Nams方式是先通过运行NativeAppManagerPeer类里的main方法,创建NativeAppManagerPeer实例,并且调用notifySystemStart发送虚拟机启动的本地消息,虚拟机状态改变为ACTIVE.
A.NativeAppManagerPeer构造时会先注册AmsIsolated,创建EventQueue,当前AMS线程即前台线程。初始化MIDletProxyList,每个proxy代表一个运行中的MIDlet。
B.processNativeAppManagerRequests
每处理完一个midletProxyList中的proxy,便删除它.
a. 当虚拟机shutdownFlag被置为true,退出虚拟机
b. 当midletProxyList大小为0时说明所有midlet均处理完毕,midpRunVm执行完毕
c. 否则ams线程wait。
2. runMidletWithJAMS
setupArgToStartMidlet-> set classNameToRun
midp_run_midlet_with_args_cp->
vmStatus = midpRunVm(classPath, MIDP_MAIN, 0, NULL);
#define MIDP_MAIN "com.sun.midp.main.MIDletSuiteLoader"
->JVM_Start(classPath, mainClass, argc, argv);
分析:
入口点为MIDletSuiteLoader的main方法,创建MIDletSuiteLoader实例,并且获取suite参数(包括midletClassName,suiteId等)
CommandState.getCommandState()
运行MIDletSuite: loader. runMIDletSuite
createSuiteEnvironment
createMIDletSuite
initSuiteEnvironment
startSurite
NAMS&JAMS区别?
守护线程和非守护线程:
守护线程通常是由虚拟机自己使用的线程(如执行垃圾收集),JAVA程序也可以把他创建的任何线程标记为守护线程;
非守护线程就是JAVA程序中的初始线程。只要非守护线程在运行,虚拟机就存活,所有非守护线程都终止时,虚拟机实例将自动退出。
2.JAVA虚拟机体系结构
A.虚拟机内部体系结构
Class文件->类装载器子系统<->运行时数据区(方法区,堆,JAVA栈,PC寄存器,本地方法栈)<->执行引擎<->
<->本地方法接口<-本地方法库
每个JAVA虚拟机实例都有一个方法去和堆,它们是由该虚拟机实例中所有线程共享的。当虚拟机装载一个class文件时,它会从这个class文件包含的二进制数据中解析类型信息。然后把这些类型信息放到方法区中。当程序运行时,虚拟机会把所有该程序在运行时创建的对象都放到堆中。
当一个新线程被创建时,它都将得到它自己的PC寄存器和一个JAVA栈。如果线程正在执行的是一个JAVA方法,则PC总是指示吓一跳将被执行的指令,而它的JAVA栈则总是存储该线程中JAVA方法的调用状态(局部变量,参数等);本地方法调用的状态则是以某种依赖于具体实现的方式存储在本地方法栈中或其他地方。
不会存储在JAVA栈中
NATIVE可以通过KNI方法读取或设置JAVA Object。
Java栈是由许多栈帧(stack frame),一个栈帧包含一个Java方法的调用的状态。当线程调用一个Java方法时,虚拟机压入一个新的栈帧到该线程的Java栈中,方法返回时,弹出并抛弃。
Java虚拟机没有寄存器,其指令集使用Java栈来存储中间数据。
Java虚拟机这种基于栈的体系结构有助于运行时某些虚拟机实现的动态编译和即使编译器代码优化。
3. 类装载器子系统
定位和导入二进制class文件->验证类的正确性->为类变量分配并初始化内存,帮助解析符号引用等
装载:查找并装载类型的二进制数据
连接:执行验证,准备,以及解析(符号引用转为直接引用)
初始化:初始化类变量为正确的初始值
启动类装载器:在系统类(Java API)的安装路径中查找要装入的类(import?)
系统类装载器(自定义),虚拟机启动时被创建,装载指定的classpath目录下的类
类在虚拟机运行前一次性装载,连接,初始化(所有需要用到的类?)