JVM虚拟机的发展与运行时数据区

虚拟机的发展

JDK1.0~1.2 : 默认使用 Classic VM ,使用纯解释方式执行代码 。如果要编译JIT,需要外挂JIT编译器;曾今改进一款 Exact VM (可准确内存管理)。
JDK1.3及后: HotSpot VM ,准确管理内存,热点代码编译。Oracle收购 Sun 公司后,将JRockit VM 的优点整合到 HotSpot 中,如使用JRockit VM垃圾回收器与MissionControl服务,使用HotSpot的JIT编译器与混合的运行时系统。

其他虚拟机:
① IBM J9 ,正式名称是“IMB Technology for Java Virtural Machine" ,简称 IT4。J9的市场定位和HotSpot比较接近。
② BEA JRockit,一款专门为服务器硬件和服务器端应用场景高度化的虚拟机;
③ Dalvik VM ,Android 平台核心组成部分之一,没有遵循Java 虚拟机规范,不能直接执行Java的Class文件,使用寄存器架构而不是JVM常见的栈架构。它执行的dex(Dalvik Executable)文件可以通过Class文件转化而来。

OpenJDK
OpenJDK : 2006年末,Sun 公司把Java开源形成的项目。Oracle JDK中还存在一些OpenJDK中没有的,商用闭源的功能,如从JRockit移植改造的Java Flight Recorder。

运行时数据区域

① 程序计数器: 较小的内存区域,当前线程执行的字节码行号指示器。为了线程切换后能恢复到正确的执行位置,每条线程都需要一个独立的程序计数器,即线程私有。如果线程正在执行一个Java方法,计数器记录的时正在执行的虚拟机字节码指令地址;如果正在执行native方法,计数器值为空。此内存区域不会发生OOM
② 虚拟机栈: 线程私有的,生命周期与线程相同。每个方法执行时都会创建一个栈帧,用于存储局部变量表,操作数栈,动态链接,方法出口等。每个方法从调用直至执行完成的过程,对应一个栈帧在虚拟机栈中入栈到出栈的过程。局部变量表存放了编译期各种基本数据类型(8种),对象引用,returnAddress类型(指向了一条字节码指令地址)。局部变量表所需要的内存空间在编译期完成分配,当进入一个方法,在栈帧中需要分配多大的空间是完全确定的。当线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflow异常。如果虚拟机允许动态过程,扩展时无法申请到足够的内存,会抛出OOM异常。
③ 本地方法栈: 与虚拟机栈相似,虚拟机栈执行Java方法服务,本地方法栈为虚拟机使用到的native方法服务。jvm可自由的实现本地方法栈。
④ Java堆: 所有线程共享的一块区域,虚拟机启动时创建。Java虚拟机规范中描述是:所有的对象实例以及数组都要在堆上分配,Java堆可以处于物理上不连续的内存空间中,只要逻辑上连续就可以。但是随着JIT编译器的发展与逃逸分析技术逐渐成熟,栈上分配,标量替换优化技术将会导致一些微妙的变化,在堆上分配也渐渐变得不那么“绝对”了。Java堆是垃圾收集器管理的主要区域,从内存回收的角度看,由于现在收集器基本采用分带收集算法,所以堆可进一步分为新生代,老年代…,从内存分配角度来看,线程共享的堆可划分多个线程私有的分配缓冲区(TLAB技术)。
⑤ 方法区: 各个线程共享的内存区域,用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。
⑥ 运行时常量池: 方法区的一部分,Class文件中除了有类的版本,字段,方法,接口等描述信息外,还有一项信息是常量池,用于存放编译器生成的各种字面量和符合引用,这部分内容将在类加载后进入方法区的运行时常量池。运行时常量池具有动态性,如String.intern();
⑦ 直接内存: 如NIO,通过堆中的DirectByteBuffer对象作为这块内存的引用进行操作,避免了Java堆和native中来回复制数据。
JVM虚拟机的发展与运行时数据区_第1张图片

参考资料:

  1. 《深入Java虚拟机》 第2版 机械工业出版社
  2. 《码出高效Java开发手册》 电子工业出版社

你可能感兴趣的:(Java)