JVM入门

JVM入门

一、什么是JVM

JVM即Java Virtual Machine (Java虚拟机)

Java虚拟机从Java诞生以来,经过了长足的发展,只要遵循Java虚拟机规范,已经诞生有很多种JVM,而官方的HotSpot VM是我们最常用,也是最当之无愧的武林盟主,其余还有Exact VM、Embedded VM、IBM VM等。后面我们将针对HotSpot来深入理解Java虚拟机的世界

1、JVM的语言无关性

我们都知道计算机只认识 0 和 1 ,所以我们编写的程序都要被转化成 0 和 1 构成的二进制格式才能被计算机执行,随着虚拟机及程序语言的蓬勃发展,把程序编写成二进制本地机器码(Native Code)已经不再符合需求,越来越多的语言选择了与操作系统和指令集无关的、平台中立的格式作为程序编译后的存储格式

与平台无关的最终理想只能实现在操作系统之上的应用层:如 Oracle 提供的 Java 虚拟机 JVM ,这些虚拟机可以载入和执行同一种平台无关的字节码,从而实现程序的 “ 一次编写,到处运行 ” ,各种不同平台的JVM,以及所有平台都统一支持的程序存储格式——字节码(Byte Code)是构成平台无关性的基石

JVM不与包含Java语言在内的任何程序语言绑定,它只与 “ Class文件 ”这种指定的二进制文件格式所关联,Class文件包含了JVM指令集、符号表以及若干其他辅助信息。作为一个通用的、与机器无关的执行平台,其他任何语言的实现者都可以将JVM作为它们语言的运行基础,以Class文件作为它们的交付媒介
JVM入门

JDK、JRE、JVM的关系:
JVM入门

Java程序从编码到执行:
JVM入门

JVM支持各种语言
JVM入门

2、JVM的平台无关性

JVM可以看作是一个软件,可以安装在任何操作系统平台上,并且能够看作是一个小型的操作系统
JVM入门

二、Class文件结构——Class File Format

Class文件是一组以8个字节为基础的单位的二进制字节流,各个数据项目严格按照顺序紧凑的排列在文件中,中间没有添加任何分隔符,这使得整个Class文件中存储的内容几乎全部都是程序运行时的必要数据,没有空隙存在

在上面我们知道:JVM的语言无关性是基于特定的字节码格式——Class文件格式。只要遵循Class文件格式,就可以运行在JVM虚拟机上,那么Class文件到底是什么格式呢?Class文件结构有以下各个部分:

1、魔数与Class文件的版本

  • 魔数:CAFEBABE
  • minor_version:小版本号
  • major_version:大版本号

2、常量池

紧随主次版本号之后的是常量池入口,常量池可以比作是 Class 文件里的资源仓库,它是 Class 文件结构中与其他项目关联的最多的数据,通常也是占用 Class 文件空间最大的数据项目之一。常量池中主要存放两大类常量:

  1. 字面量
  2. 符号引用

1、字面量

字面量:比较接近Java语言层面的常量概念,如文本字符串、被声明为final的常量值等

2、符号引用

符号引用:属于编译原理方面的概念,Java代码在进行Javac编译的时候,并不像 C 和 C++ 那样有 “ 连接 ” 这一步骤,而是在JVM加载Class文件(类加载)的时候进行动态连接,也就是说,在Class文件中不会保存各个方法、字段等最终在内存中的信息,这些字段、方法的符号引用不经过虚拟机在运行期转换的话是无法得到真正的内存入口地址,也就无法直接被 JVM 使用的

当虚拟机做类加载的时候,将会从常量池获得对应的符号引用,再在类创建时或运行时解析、翻译到具体的内存地址中

类加载过程将在下一篇中详解

常量池的信息相当复杂,各种指令集意义可以从官方文档中查看(我们小白就别看了,没有意义)。

java中只有8个指令是原子性的,其他的所有指令都不是原子性的,会出现指令重排

所以这也是多线程中锁的意义及重要性所在——保证原子性,多线程安全

3、访问标记

访问标志:access_flags——识别访问信息,比如Class是类还是接口、访问修饰符是否是public、是否被声明为final等

4、类索引、父类索引与接口索引集合

这三项数据用来确定该类型的继承关系

5、字段表集合

字段表集合:field_info——用来描述接口或者类中声明的变量

6、方法表集合

方法表集合:method_info

7、属性表集合

属性表集合:attribute_info——Class文件、字段表、方法表都可以携带自己的属性表集合,以描述某些场景专有的信息。此集合内属性很多,且较复杂

8、总结

Java能够一直保持非常良好的向后兼容性,Class文件结构的稳定性功不可没,Class文件结构这么多年来,几乎没有发生过什么改变。整个Class文件格式就是二进制字节流,由Java虚拟机JVM来解释执行,解释出来的16进制字节码示例如下:
JVM入门

对上面字节流的解释:这里只是解释了最前面的几个字节的意义,其余的也是了解即可。

这部分很难,也没必要深究,了解即可

JVM入门
JVM入门

一个程序的详细二进制字节码的指令可以通过IDEA中下载一个对应的插件即可查看

三、字节码指令集

将字节码操作按用途,大致分为9类:

  1. 加载与存储指令
  2. 运算指令
  3. 类型转换指令
  4. 对象创建与访问指令
  5. 操作数栈管理指令
  6. 控制转移指令
  7. 方法调用和返回指令
  8. 异常处理指令
  9. 同步指令

指令集部分了解有这个概念即可——程序到最后都是解析成指令集,交给操作系统运行

四、总结

JVM虚拟机应有的公共的程序存储格式:

  1. Class文件格式
  2. 字节码指令集

这些内容与硬件、操作系统和具体的Java虚拟机实现之间是完全独立的。Class文件是Java虚拟机执行引擎的数据入口,也是Java技术体系的基础支柱之一,可以把他们看做程序在各种Java平台实现之间安全的交互的手段。

相较于语言、API以及Java技术体系中其他方面的变化,Class文件结构一直处于一个相对比较稳定的状态——Class文件的主体结构、字节码指令的语义和数量这么多年几乎没有出现过变动

Class文件格式所具备的平台中立(不依赖于特定硬件及操作系统)、紧凑、稳定和可扩展的特点,是Java技术体系实现平台无关、语言无关两项特性的重要支柱

参考:《深入理解JVM虚拟机》 第6章