本专栏学习内容来自尚硅谷宋红康老师的视频以及《深入理解JVM虚拟机》第三版
有兴趣的小伙伴可以点击视频地址观看,也可以点击下载电子书
从某些程度上来讲,Java虚拟机是比Java语言更成功的软件,这真正的让Java语言实现了一次编译,到处运行
下图描述了JVM所处的位置,熟悉Java的小伙伴都知道,.java文件通过编译成,class文件,也就是我们所说的字节码文件,而JVM对字节码文件进行一些列的操作转换成各个操作系统所能看懂的汇编语言,从而执行命令。
JVM是运行在操作系统上的,跟硬件没有直接的交互

在面试中经常被问到JDK,JRE两者有什么区别
如果单单想要运行Java程序,只需要安装JRE即可,而从事Java开发必须要安装JDK,JDK可以把编写的.java文件编译成JVM可以读懂的.class文件

下图是JVM的整体结构,之后学习的路线就会按照下图来一步步学习
这里主要提一下执行引擎,Java文件到被系统执行一共经历了两次编译
第一次就是前面说的前端编译器,将.java文件编译成.class文件,因为JVM所能读懂的只有.class文件。
第二次在执行引擎中,无论是Java、c、python都属于高级语言,计算机操作系统是无法识别该语言的,而执行引擎可以将.class文件编译成计算机能识别的语言(汇编语言)
另外在运行时数据区中,标红的两块(方法区和堆)中的东西多线程时共享的

Java编译器输入的指令流基本上是一种基于栈的指令集架构,另外一种指令集架构则是基于寄存器的指令集架构
一段比较简单的程序
public class StackTest {
public static void main(String[] args) {
int i = 2;
int j = 3;
int m = i + j;
}
}
编译之后,我们通过反编译查看class文件
# 指令
javap -v .\StackTest.class
# 结果
stack=2, locals=4, args_size=1
0: iconst_2 #生成常量2
1: istore_1 #保存在索引为1的位置
2: iconst_3 #生成常量3
3: istore_2 #保存在索引为2的位置
4: iload_1 #加载第一个位置的值
5: iload_2 #加载第二个位置的值
6: iadd #相加
7: istore_3 #将结果保存在索引为3的位置
8: return
Java虚拟机的启动是通过引导类加载器(bootstrap class loader)创建一个初始类(initial class)来完成的,这个类是由虚拟机的具体实现指定的
在上述程序中添加一个睡眠任务,方便我们观察Java虚拟机的进程
public class StackTest {
public static void main(String[] args) {
int i = 2;
int j = 3;
int m = i + j;
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
通过jps指令,可以查看Java虚拟机中的进程,我们可以看到在运行中时会多一个StackTest的进程
# 程序运行中
PS D:\Desktop\Study\JVM\jvm\practice1\target\classes\com\example\practice1> jps
10400 StackTest #虚拟机的进程
12448
17696 Launcher
9648 RemoteMavenServer36
16676 RemoteMavenServer36
10108 Jps
15276 RemoteMavenServer36
# 程序运行结束
PS D:\Desktop\Study\JVM\jvm\practice1\target\classes\com\example\practice1> jps
12448
17696 Launcher
9648 RemoteMavenServer36
16676 RemoteMavenServer36
15276 RemoteMavenServer36
8124 Jps
System类的exit方法,实际上调用了Runtime类的exit方法

而无论是Runtime类中的exit方法还是halt方法,最终都会调用Shutdown类中的halt方法对线程进行种植
