计算机的基本构成是:运算器、控制器、存储器、输入和输出设备,JVM 也是有这成套的元素,运算器还是交给硬件CPU 处理,通过JVM 的命令集达到“一次编译,随处运行”的目的,JVM 做了一个翻译,根据不同的CPU ,翻译成不同的机器语言。JVM 是一个内存中的虚拟机,它的存储就是内存,我们写的所有类、常量、变量、方法都在内存中。JVM运行在操作系统之上,与硬件没有直接的交互。
Class Loader类加载器的作用是加载类文件到内存,Class Loader 只管加载,加载的class 文件是有格式要求,只要符合文件结构就加载,至于说能不能运行,则是由Execution Engine 负责的。类加载器本身也是一个类,平时几乎不需要关心类的加载,因为这些都是隐式装载的( 程序在运行过程中当碰到通过new 等方式生成对象时,隐式调用类装载器加载对应的类到jvm中),当有特殊的用法例如反射,就需要通过class.forname()等方法显式的加载所需要的类。
ClassLoader分为三种:
1)Bootstrap Loader负责加载系统类,如%JAVA_HOME%/jre/lib 目录中或 -Xbootclasspath 中参数指定的路径中的,并且能被虚拟机识别的类库,无法被 Java 程序直接引用;
2)ExtClassLoader负责加载扩展类,如%JAVA_HOME%/lib/ext 或者由 java.ext.dirs 系统变量指定的路径中的所有类库,开发者可以直接使用扩展类加载器;
3)AppClassLoader负责加载应用类即程序员自定义的类;
ClassLoader的加载机制:双亲委托模型,要求除了 Bootstrap ClassLoader 外,其余的类加载器都要有自己的父加载器。子加载器通过组合来复用父加载器的代码,而不是使用继承。当一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把请求委托给父加载器去完成,依次向上,因此,所有的类加载请求最终都应该被传递到顶层的启动类加载器中,只有当父加载器在它的搜索范围中没有找到所需的类时,子加载器才会尝试自己去加载该类。双亲委派模型最大的好处就是让Java类同其类加载器一起具备了一种带优先级的层次关系。从安全上考虑,可以防止有人将恶意的基础类加载进JVM,因为无法找到该类对应的类加载器。
ClassLoader的加载步骤:首先是装载:查找和导入class文件;接下来是连接:检查载入的class文件数据的正确性,为类的静态变量分配存储空间,然后解析,也就是将符号引用转换成直接引用;最后初始化静态变量,静态代码块。这个过程在程序调用类的静态成员时开始执行,所以静态方法main()才会成为一般程序的入口方法。类的构造器也会引发该动作。
Execution Engine 执行引擎也叫做解释器(Interpreter) ,负责解释命令,提交操作系统执行。
Native Interface 本地接口的作用是融合不同的编程语言为Java 所用,它的初衷是融合C/C++ 程序,在Native Method Stack 中登记native 方法,在Execution Engine 执行时加载native libraies 。
我们所有写的程序都被加载到Runtime data area 运行数据区,之后才开始运行。