### 一、JVM简述
Java是目前应用最为广泛的软件开发平台之一。随着Java以及Java社区的不断壮大,Java也早已不再是简简单单的一门计算机语言了,它更是一个平台、一种文化、一个社区。Java语言具有跨平台的特点,即“Write once,run everywhere”——一次编写,到处运行。之所以会有这样的特点,主要原因是Java程序运行的平台Java虚拟机(JVM,Java Virtual Machine) 具有跨平台的特点。

JVM运行在操作系统之上,与机器的硬件没有直接的交互。

JVM是一台执行Java字节码的虚拟计算机(软件层面),它是Java技术的核心,因为所有的Java程序都运行在Java虚拟机内部。JVM拥有独立的运行机制,其运行的字节码文件也未必由Java语言编译而成,Kotlin、Scala等语言所编写的程序经过编译后生成的字节码文件也可以在JVM上运行。JVM平台的各种语言可以共享Java虚拟机带来的跨平台性、优秀的垃圾回器,以及可靠的即时编译器。

### 二、各种JVM
从Java语言诞生开始,就涌现出很多优秀的JVM,按照时间顺整理如下:
- **Sun Classic VM(世界上第一款商用JVM)**:在1996年Java l.0版本的时,由Sun公司发布,JDK 1.4时完全被淘汰。这款虚拟机内部只提供解释器。如果使用JIT编译器,就需要进行外挂。但是,一旦使用了JIT编译器,JIT就会接管虚拟机的执行系统。解释器就不再工作。解释器和编译器不能配合工作。现在hotspot内置了此虚拟机。
- **Exact VM**:jdk 1.2时,由Sun提供,主要为了为了解决上一个虚拟机问题,具有热点探测、编译器与解释器混合工作模式。但最终还是被Hotspot虚拟机替换。
- **HotSpot VM**:JDK 1.3时,HotSpot VM成为默认虚拟机,是目前最有影响力的三大商用虚拟机之一。同时Hotspot VM占有绝对的市场地位。
- **JRockit**:由BEA公司提供,专注于服务器端应用,是目前最有影响力的三大商用虚拟机之一。它不太关注程序启动速度,因此JRockit内部不包含解析器实现,全部代码都靠即时编译器编译后执行,所以JRockit JVM是世界上最快的JVM。
- **J9**:IBM Technology for Java Virtual Machine,简称IT4J,内部代号: J9,由IBM主导开发。J9市场定位与Hotspot接近,服务器端、桌面应用、嵌入式等多用途VM广泛用于IBM的各种Java产品。
- **KVM和CDC/CLDC Hotspot**:Oracle在Java ME产品线上的两款虚拟机。
- **Azul VM和BEA liquid VM**:Azul VM和BEA Liquid VM是与特定硬件平台绑定、软硬件配合的专有虚拟机,是高性能Java虚拟机中的战斗机。
- **Apache Harmony**:Apache推出的与JDK 1.5和JDK 1.6兼容的Java运行平台Apache Harmony。它是IBM和Intel联合开发的开源JVM。
- **Microsoft JVM**:微软为了在IE3浏览器中支持Java Applets, 开发了Microsoft JVM。已夭折。
- **TaobaoJVM**:由AliJVM团队发布。Taobao vm应用在阿里产品上性能高,硬件严重依赖intel的cpu,损失了兼容性,但提高了性能。目前已经在淘宝、天猫上线,把oracle 官方JVM版本全部替换了。
- **Dalvik VM**:谷歌开发的,应用于Android系统,并在Android2.2中提供了JIT,发展迅猛。Dalvik VM只能称作虚拟机,而不能称作“Java 虚拟机”,它没有遵循Java虚拟机规范。
- **Graal VM**:2018年4月,Oracle Labs公开了Graal VM, 号称"Run Programs Faster Anywhere", 勃勃野心。Graal VM在Hotspot VM基础上增强而成的跨语言全栈虚拟机。可以作为任何语言的运行平台使用。语言包括:Java、Scala、Groovy、JavaScript、Ruby、Python、R等。
### 三、JVM的整体结构
HotSpot VM是目前市面上高性能虚拟机的代表作之一。以Hotspot为例,JVM包含**类加载器子系统**(Class Loader SubSystem)、**运行时数据区**(Runtime Data Area)、**执行引擎**(Execution Engine)、**本地方法接口**(Native Interface)、**本地方法库**(Native Method Library)五部分,其中运行时数据区包含**方法区**(Method Area)、**Java栈**(Java Stack)、**本地方法栈**(Native Method Stack)、**堆**(Heap)、**程序计数器**(Program Counter Register,也叫PC寄存器)五部分内容。其整体结构如下图

1. 方法区和堆区是所有线程共享的内存区域;而java栈、本地方法栈和程序员计数器是线程私有的内存区域。
2. Java栈又叫做jvm虚拟机栈。
3. 方法区(永久代)在jdk8中又叫做元空间Metaspace。方法区用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器(JIT编译器,英文写作Just-In-Time Compiler)编译后的代码等数据。虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做 Non-Heap(非堆),目的应该是与 Java 堆区分开来。
- 在JDK1.7之前运行时常量池逻辑包含字符串常量池存放在方法区, 此时hotspot虚拟机对方法区的实现为永久代。
- 在JDK1.7 字符串常量池被从方法区拿到了堆中, 这里没有提到运行时常量池,也就是说字符串常量池被单独拿到堆,运行时常量池剩下的东西还在方法区, 也就是hotspot中的永久代。
- 在JDK1.8之后JVM 已经将运行时常量池从方法区中移了出来,在 Java 堆(Heap)中开辟了一块区域存放运行时常量池。同时在 jdk 1.8中移除整个永久代,取而代之的是一个叫元空间(Metaspace)的区域。
### 四、JVM的生命周期
#### 1、 虚拟机的启动
Java,虚拟机的启动是通过引导类加载器(bootstrap class loader) 创建一个初始类(initial class) 来完成的,这个类是由虛拟机的具体实现指定的。
#### 2、虚拟机的执行
一个运行中的Java虚拟机有着一个清晰的任务:执行Java程序。程序开始执行时它才运行,程序结束时它就停止。执行一个所谓的Java程序的时候,真真正正在执行的是一个叫做Java虚拟机的进程。
#### 3、虚拟机的退出
当有如下的几种情况时,JVM会退出:
- 程序正常执行结束;
- 程序在执行过程中遇到了异常或错误而异常终止;
- 由于操作系统出现错误而导致Java虚拟机进程终止;
- 某线程调用Runtime类或System类的exit方法,或Runtime类的halt方法,并且Java安全管理器也允许这次exit或halt操作。
- 除此之外,JNI ( Java Native Interface) 规范描述了用JNI Invocation API来加载或卸载Java 虚拟机时,Java虚拟机也会退出。

循序渐进Java虚拟机-JVM概述