Java宣称Write Once Run Everywhere,这意味着在一个平台上开发的java程序可以不加修改的运行在其他平台上面。能达成这个功能依赖的就是jvm屏蔽了底层的差异。
当我们编写.java文件之后,编译器会将其编译成同名的.class文件。class文件是一个字节码文件,jvm会加载并且执行它,下方就是整体框图。
如图所示,虚拟机主要可以被分为三块:
1.类加载系统
2.运行时数据区
3.执行引擎
类加载系统Class Loader Subsystem
类加载系统负责验证并且加载.class文件,主要可以划分为三个步骤:
1.加载(Loading)
2.链接(Linking)
3.初始化(Initialization)
加载
类文件在这一块被加载到内存中去。类加载器(class loader)可以划分为Boot Strap class Loader, Extension class Loader, and Application class Loader
1. Boot Strap class Loader - 加载系统引导类( $JAVA_HOME/jre/lib))
2. Extension class Loader - 加载拓展类($JAVA_HOME/jre/lib/ext)
3. Application class Loader - 也被称为User class loader, 负责加载应用层级的类
链接
1. Verify - 验证字节码是否正确
2. Prepare - 在这一步分配静态变量并且设置默认值
3. Resolve - 所有的符号引用都会被替换成指向方法区的原始引用
初始化
这是类加载的最后一步,所有的静态变量都会被赋值。执行顺序是从上到下的,由父类到子类。
运行时数据区 Runtime Data Area
运行时数据区可以划分为5个区域
1. 方法区 - 保存类数据信息,包括成员信息,父类和接口信息,运行时常量池等,jvm共享
2. 堆区 - 保存所有的对象信息,jvm共享
3. 栈区 - 每个线程独有自己的栈,生命周期和线程一致
4. PC寄存器区 - 储存当前执行指令的地址,如果执行的是是本地方法pc为null
5. 本地方法栈区 - 和栈区一致,只不过存放的是本地方法信息
执行引擎 Execution Engine
执行引擎负责执行代码,执行引擎会依次读取字节码并且按顺序执行。一般来说可以划分为如下几个组件
字节码解释器
字节码解释器(Bytecode Interpreter),就像名字显示的一样,是用来执行字节码。优点是执行开销小,缺点是执行效率较低。
模板解释器
和字节码解释器差不多,不一样的地方在于直接把对应的指令集转成本地代码
JIT编译器
可以针对热点代码优化,执行开销较大,但是能够针对性的优化,效率最高
垃圾收集器
负责回收不再使用的对象,释放和整理内存
Java Native Interface
Java native interface, 简称JNI。暴露了本地方法的接口,使得java可以调用本地方法
Native Method Libraries
本地方法库
参考: