我的JVM学习笔记:第一章——JVM概述

我的JVM学习笔记:第一章——JVM概述

感谢尚硅谷宋红康老师的JVM入门到精通课程,向每一个用心做免费教课程的老师致敬!
本套教程均为我学习课程之后的学习笔记,防止遗忘,并发送给大家分享,感谢大家查看~

一.、JVM概念

JVM是Java Virtual Machine(Java虚拟机)的缩写,引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译,一个字节码文件可以直接跨平台运行。

本质上说:
Java编译程序,并不是将源代码直接编译为机器指令,而是编译为Java虚拟机可以识别的字节码文件,JVM直接按照字节码文件中的命令依次执行!所有平台的JVM虚拟机都执行统一规范,所以编程时病不需要考虑操作系统,因为字节码文件并不直接作用于(执行在)操作系统,而是被JVM识别,由JVM对操作系统进行操作!
举个例子:

  • 以前有个经理叫C语言。 经理只会操作一种类型的机器(C语言直接编译成机器指令)。
  • 这个时候,假如说工厂需要临时使用经一套设备,经理就需要重新学习(到新的平台重新编译)。 而这个时候名为Java的经理出现了
  • 这个经理很聪明,雇佣了一个技术工程师,这个工程师可以同时操作所有机器。
  • 这样,经理有什么命令,就直接下达给工程师,而不直接操作机器,工程师接到经理的命令,在机器上进行操作!
  • 虽然此时,完成同样的工作多了一个操作员,但经理可以什么都不会,只要可以对工程师下命令就可以了,工厂更换新设备时,不需要经理亲自学习!

二、 Java和 JVM的关系

  • Java:Java是一门编程语言,由Java编写的代码会被编译器翻译为.class后缀的字节码文件,字节码文件需要符合JVM规范,由Java虚拟机执行。
  • JVM:用来执行字节码文件,但是并不是只有Java的字节码文件可以被执行。 只要符合JVM规范的字节码文件都可以被JVM所执行,所以也可以使用其他的编程语言进行代码编写,只要编译器将源码编译成符合JVM规范的的字节码文件,就可以使用JVM来运行!
    总结来说:
    Java是跨平台的序言,JVM是跨语言的平台,JVM并不只可以执行Java代码编译的字节码,这也为多语言混合编程成为可能性!
    我的JVM学习笔记:第一章——JVM概述_第1张图片

三、JVM整体结构

3.1、JVM版本概述
Java有很多版本的虚拟机,目前我们使用最多的JDK是JDK8,默认使用的是HotSpot虚拟机。Hotspot虚拟机也是目前最常用的Java虚拟机,本笔记讲述的就是HotSpot虚拟机!
 查看JVM版本命令:

java –version

查看虚拟机版本
注意:并不是所有的虚拟机都是此结构,此笔记只针对于HotSpot虚拟机

3.2、Java程序执行流程
我的JVM学习笔记:第一章——JVM概述_第2张图片
可以由此图得知:

  1. 编写Java代码,生成.java格式的文件
  2. 编译器在进行分析后,生成符合规范的.class的字节码文件
  3. 字节码由被JVM的类加载子系统读取,校验,如果符合国凡,则由执行引擎进行执行
  4. 执行引擎根据字节码文件操作操作系统

3.3、JVM的位置
我的JVM学习笔记:第一章——JVM概述_第3张图片
JVM是运行在操作系统之上的,与硬件没有直接交互。

3.4、JVM的结构
类加载子系统:
将字节码文件读取到运行时数据区,生成Class对象,其中读取过程大体有:加载、链接、初始化。
在笔记此章节不重点讲述,第二章(类加载子系统)章节中会详细描述

运行输数据区
类加载子系统读取.class字节码文件后,会加载到运行时数据区,其中包含方法区、堆、Java栈(虚拟机栈)、本地方法栈,程序计数器5部分组成。其中方法区和堆区(红色部分)是由整个进行所共有,虚拟机栈,本地方法栈,程序计数器(灰色部分)由线程独有!
其中:GC(垃圾回收)就是发生在运行输数据区中的堆区
在笔记此章节不重点讲述,第二章(运行时数据区)章节中会详细描述
执行引擎
由于操作系统并不能直接运行字节码文件,所以必须交由执行引擎进行执行,其中包含解释器(解释执行字节码文件)、JIT即时编译器(将热点代码直接编译为机器指令,加快运行速度),垃圾回收器。
我的JVM学习笔记:第一章——JVM概述_第4张图片

四、 JVM架构模型

目前的指令流有两种指令集架构,一种是基于栈的指令集架构,另一种是基于寄存器的指令集架构。而JVM采用的几乎都是基于栈的指令集架构,因为这种架构不具体依赖硬件,能有很好的可移植性。
基于栈的虚拟机:

  • 设计和实现更简单,编译更容易,指令集更少,执行时只需要入栈和出栈,但是完成相同操作时的指令更多,适用于资源受限的系统。
  • 避开了寄存器分配的问题,使用零地址指令分配(直接操作数据,操作时不实用地址),执行过程依赖于操作栈,编译器更容易实现。
  • 不需要硬件支持,更好的跨平台性。

基于寄存器的虚拟机:

  • 性能更加优秀,花费更少的时间执行相同指令,完成相同操作使用的指令更少,但是指令集也相对更大
  • 指令级架构依赖于硬件支持,可移植性比较差
  • 大部分情况下,使用一地址指令和二地址指令等,而栈使用的大多是零地址执行

区别举例:
反编译Java代码的命令:

javap –v *.class

同样执行2+3的操作,基于栈的指令有8条,而基于寄存器的指令只有两条

  • 基于栈的计算步骤(以Java虚拟机为例):
    我的JVM学习笔记:第一章——JVM概述_第5张图片

  • 基于寄存器的计算步骤:
    基于寄存器的计算
    那么在此提出问题问题:

  • 目前嵌入式环境已经不是Java的主流环境,为什么不讲Java虚拟机更换为基于寄存器的架构呢?

      基于栈的操作更简单,只需要将栈贞进行入栈和出栈的操作即可,实现更简单。
      并且,非自愿受限的环境中也可以使用。还做到了更好的跨平台性。
      所以,目前暂时没必要更换!
    

五、JVM的生命周期

JVM随进程的启动而启动,一个Java程序运行,就启动了一个Java虚拟机,当这个程序运行结束,Java虚拟机就会运行消亡,每运行一个Java程序都会运行一个JVM!
所以,Java程序执行时,真正执行的是一个叫Java虚拟机的进程!

在笔记此章节不重点讲述,第二章(类加载子系统)章节中会详细描述
JVM的启动
Java虚拟机的启动是通过引导类加载器(bootstrap class loader) 创建一个初始类(initial class) 来完成的,这个类是由虚拟机的具体实现指定的。
也就是说:JVM执行时启动,创建引导类加载器,引导类加载器会将使用到的类加载到运行时数据区,并且会配置JVM使用的参数,之后JVM会自动执行程序中的main方法。
也可以说:伴随进程启动、伴随启动类的Main方法而启动。
JVM的运行
只有此进程中有非守护线程执行(Main方法所启动的线程,用户启动的线程),JVM就会一直执行。
JVM的退出
Java程序运行结束,也就是程序中的所有非守护线程都终止时,JVM才退出。
有几种情况:

  • Java程序程序运行结束,JVM会退出。
  • 程序运行时发生了非处理异常,JVM会退出。
  • 调用了exit等方法,JVM会退出。

这是第一章的内容,全部是JVM的一个简单认识,不久就会更新第二章,感谢大家观看~

你可能感兴趣的:(我的JVM学习笔记)