JVM篇(01.JAVA体系与JVM)
关于JVM,可能我们最大的印象就是JDK、JRE和JVM三者的关系。然后就是有些程序可能需要比较大的堆内存,需要在启动配置上配置:-Xms -Xmx等。我记得我第一份工作是做银行系统的,当时系统比较老,没有用到redis缓存,然后程序启动的时候就会创建比较多的监听对象和缓存对象,当时我们就需要配置-Xms -Xmx这两个参数,否则程序会出现OOM。那么我们就从JDK、JRE及JVM三者的关系开始,深入的了解下JVM。
JDK、JRE和JVM三者的关系
-
Java Development Kit
JDK(Java Development Kit),即Java开发工具包,是针对Java开发员的产品,是整个Java的核心,包括了Java运行环境JRE、Java工具和Java基础类库。通过查看JDK的目录结构,可以通俗的理解为:JDK中包含jre,在JDK的安装目录下有一个名为jre的目录,里面有两个文件夹bin和lib,在这里可以认为bin里的就是jvm,lib中则是jvm工作所需要的类库,而jvm和 lib加起来就称为jre。
-
Java Runtime Environment
JRE(Java Runtime Environment),即java运行时环境,是运行JAVA程序所必须的环境的集合,包含JVM标准实现及Java核心类库。也是通过它,Java的开发者才得以将自己开发的程序发布到用户手中,让用户使用。JRE中包含了Java virtual machine(JVM),runtime class libraries和Java application launcher,这些是运行Java程序的必要组件。与大家熟知的JDK不同,JRE是Java运行环境,并不是一个开发环境,所以没有包含任何开发工具(如编译器和调试器),只是针对于使用Java程序的用户。
-
Java Virtual Machine
JVM(Java virtual machine),即java虚拟机,它是整个java实现跨平台的最核心的部分,所有的java程序会首先被编译为.class的类文件,这种类文件可以在虚拟机上执行。也就是说class并不直接与机器的操作系统相对应,而是经过虚拟机间接与操作系统交互,由虚拟机将程序解释给本地系统执行。只有JVM还不能成class的执行,因为在解释class的时候JVM需要调用解释所需要的类库lib,而jre包含lib类库。JVM屏蔽了与具体操作系统平台相关的信息,使得Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。
在jdk目录下面有五个文件夹、一个src类库源码压缩包和几个声明文件,其他五个文件夹分别是:bin、db、include、lib、 jre,db这个文件看业务需求~
- bin:最主要的是编译器(javac.exe)、jvm分析工具(jvisualvm.exe)等其他应用程序。
- db:jdk从1.6之后内置了Derby数据库,它是是一个纯用Java实现的内存数据库,属于Apache的一个开源项目。用Java实现的,所以可以在任何平台上运行;另外一个特点是体积小,免安装,只需要几个小jar包就可以运行了。
- include:java和JVM交互用的头文件;
- lib:常用类库;
- jre:java运行环境;
JDK包含JRE,而JRE包含JVM,总的来说JDK是用于java程序的开发,而jre则是只能运行class而没有编译的功能,Eclipse、IntelliJ IDEA等其他IDE有自己的编译器而不是用JDK bin目录中自带的。
JVM概述
jvm(java virtual machine),即java虚拟机。所谓的虚拟机是指:通过软件模拟的具有完整硬件系统功能的、运行在一个完全隔离环境中的计算机系统。jvm是通过软件来模拟java字节码的指令集,是java程序的运行环境。
扩展:所谓的虚拟机(Virtual Machine),就是一台虚拟的计算机。它是一款软件,用来执行一系列虚拟计算机指令。大体上,虚拟机可以分为系统虚拟机和程序虚拟机。
-
大名鼎鼎的Visual Box,VMware就属于系统虚拟机,它们完全是对物理计算机的仿真,提供一个可运行完整操作系统的软件平台。
-
程序虚拟机的典型代表就是java虚拟机,它专门为执行单个计算机程序而设计,在java虚拟机中执行的指令我们称为java字节码指令。
无论是系统虚拟机还是程序虚拟机,在上面运行的软件都被限制于虚拟机提供的资源中。
JVM的主要功能
- 通过ClassLoader寻找和装载class文件
- 解释字节码成为指令并执行,提供class文件的运行环境
- 进行运行期间的内存分配和垃圾回收
- 提供与硬件交互的平台
JVM是java语言平台无关性及语言无关性的保障,java程序编译后的.class文件只能运行在JVM,但它不会关心具体JVM运行在什么操作系统上。有人说过:“java也许不是最NB的语言,但java虚拟机绝对是最NB虚拟机”。因为JVM的存在,使跨语言编程成为可能,只要将不同的编程语言编译成符合jvm规范的class文件即可。
JVM架构(Hotspot VM)
这里讲的JVM都是Hotspot虚拟机。HotSpot VM是目前市面上高性能虚拟机的代表之一(Sun/Oracle JDK中和OpenJDK的默认虚拟机)。它采用解释器与即时编译器并存的架构。
扩展:Hotspot VM名称中的HotSpot指的就是它的热点代码探测技术,即:通过计数器找到最具编译价值代码,触发即时编译或栈上替换;通过编译器与解析器协调工作,在最优的程序响应时间与最优执行性能中取得平衡。
Java编译器输入的指令流基本上分为两种:一种基于栈的指令集架构,另外一种指令集架构则是基于寄存器的指令集架构。
-
基于栈式架构的特点(HotSpot属于栈式架构)
-
设计和实现更简单,适用于资源受限(打印机,机顶盒等)的系统
-
避开了寄存器的分配难题:使用零地址指令方式分配(只对栈顶元素进行操作)
-
指令流中的指令大部分是零地址指令,其执行过程依赖于操作栈。指令集更小,编译器容易实现
-
不需要硬件支持,可移植性更好,更好实现跨平台
看如下代码:
public class StackStructTest {
public static void main(String[] args) {
int i = 2;
int j = 3;
int k = i + j;
}
}
使用javap(反编译工具)查看class文件:
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=4, args_size=1
0: iconst_2
1: istore_1
2: iconst_3
3: istore_2
4: iload_1
5: iload_2
6: iadd
7: istore_3
8: return
可以看到简单的几行代码,编译成class后会变成较多的指令,但是这些指令都是比较简单的(都是一些加载、存储操作等)。
基于栈式架构的优缺点:优点是跨平台性、指令集小、指令多;缺点是执行性能比寄存器差。
-
基于寄存器架构的特点
-
典型的应用是x86的二进制指令集:比如传统的PC以及Android的Davlik虚拟机
-
指令集架构则完成依赖硬件,可移植性差,性能优秀和执行更高效
-
花费更少的指令去完成一项操作
-
在大部分情况下,基于寄存器架构的指令集往往都以一地址指令、二地址指令、三地址指令为主,而基于栈式架构的指令集却是以零地址指令为主
JVM的生命周期
-
虚拟机的启动
Java虚拟机的启动是通过引导类加载器(bootstrap class loader)创建一个初始类(initial class)来完成的,这个类是由虚拟机的具体实现指定的。
-
虚拟机的执行
-
一个运行中的java虚拟机有着一个清晰的任务:执行Java程序
-
程序开始执行时它才运行,程序结束时它就停止
-
执行一个所谓的java程序的时候,真正在执行的是一个叫做Java虚拟机的进程
-
虚拟机的退出
-
程序正常执行结束
-
程序在执行过程中遇到了异常或错误而异常终止
-
由于操作系统出现错误而导致Java虚拟机进程终止
-
某线程调用Runtime类或System类的exit方法,或Runtime类的halt方法,并且Java安全管理也允许这次exit或halt操作
JVM结构
运行时数据区的详细结构如下
这里简单展示下JVM的结构,后续会结合JVM规范来给大家详细介绍每个部分的功能及应用。