适合人群:想要了解JVM的朋友
说明:这一专题的文章本文主要从大局观上讲解JVM
我们写的java文件,电脑为啥可以去执行?
在我们使用了springboot,ssm,ssh框架去开发我们系统后,有没有去想过一个问题,电脑为啥可以执行我所写的java文件?
科班生应该都知道cpu只识别一种指令,那就是机器指令,也就是二进制0,1这种指令。
对于java编程来说,并不像我们想象中那么复杂。这里,我们先对java编程语言的编译和执行进行一个整体的了解。我们可以用两个阶段来概括,一是java代码的编译阶段,二是java程序的运行阶段。
在java代码的编译阶段,主要的任务是将编写好的xxx.java的源代码文件在dos命令窗口中使用java的编译器工具javac将.java后缀的java源文件编译为一个或者多个.class后缀的字节码文件(这里的字节码文件并非是二进制文件)。
在java运行阶段,需要使java.exe的运行工具将编译后的.class后缀的字节码文件加载到java虚拟机JVM中,此时java虚拟机JVM会启动加载器classloader,classloader会在硬盘中搜索.class 的字节码文件,并能够将该字节码文件装载到JAVA虚拟机JVM中并解释为二进制文件,然后JAVA虚拟机JVM会执行该二进制文件和底层硬件平台进行交互。这就是整个java编程的编译和执行过程。
JVM,JDK,JRE之间的区别
了解JVM的前提,我们要明确区分开JVM,JDK,JRE是什么,区别是什么。
JDK :Java Development Kit 是Java的标准开发工具包(普通用户只需要安装 JRE来运行 Java 程序。而程序开发者必须安装JDK来编译、调试程序)。它提供了编译、运行Java程序所需的各种工具和资源,包括Java编译器、Java运行环境JRE,以及常用的Java基础类库等,是整个JAVA的核心。
上图是我们window安装jdk的目录
- bin文件里面存放了JDK的各种开发工具的可执行文件,主要的是编译器(javac.exe)
- db文件是一个先进的全事务处理的基于Java技术的数据库(jdk自带数据库db的使用)
- include文件里面是Java和jvm交互用的头文件
- jre为java运行环境
jre:Java runtime environment 是运行基于Java语言编写的程序所不可缺少的运行环境,用于解释执行Java的字节码文件。从JDK的目录下有jre目录,就可以看出jdk是包含jre的。(ps:从JDK11开始,JDK和JRE都是在一起的,安装后默认是没有JRE的。)
JVM:Java Virtual Machine 是Java的虚拟机,是JRE的一部分。它是整个java实现跨平台的最核心的部分,负责解释执行字节码文件,是可运行java字节码文件的虚拟计算机。
总结:
- JVM不能单独搞定class的执行,解释class的时候JVM需要调用解释所需要的类库lib。在JDK下面的的jre目录里面有两个文件夹bin和lib,在这里可以认为bin里的就是jvm,lib中则是jvm工作所需要的类库,而jvm和 lib和起来就称为jre。JVM+Lib=JRE。总体来说就是,我们利用JDK(调用JAVA API)开发了属于我们自己的JAVA程序后,通过JDK中的编译程序(javac)将我们的文本java文件编译成JAVA字节码,在JRE上运行这些JAVA字节码,JVM解析这些字节码,映射到CPU指令集或OS的系统调用。
区别:
- 在bin文件夹下会发现,JDK有javac.exe而JRE里面没有,javac指令是用来将java文件编译成class文件的,这是开发者需要的,而用户(只需要运行的人)是不需要的。JDK还有jar.exe, javadoc.exe等等用于开发的可执行指令文件。这也证实了一个是开发环境,一个是运行环境。
- JVM并不代表就可以执行class了,JVM执行.class还需要JRE下的lib类库的支持,尤其是rt.jar。
JVM概述介绍
上面大致介绍了java的编译,运行过程。现在我们着重介绍jvm
JVM是java的核心和基础,在java编译器和os平台之间的虚拟处理器。它是一种利用软件方法实现的抽象的计算机基于下层的操作系统和硬件平台,可以在上面执行java的字节码程序。java编译器只要面向JVM,生成JVM能理解的代码或字节码文件。Java源文件经编译成字节码程序,通过JVM将每一条指令翻译成不同平台机器码,通过特定平台运行。
- jvm在计算机中所处的位置
jvm并不和硬件直接交互,而是直接运行在操作系统之上的。所以我们安装jdk时是需要选择操作系统(包括64位/32位)的
java一次编译,到处运行
如上图所示,我们在window系统上开发的代码,编译(打jar包)后,是可以直接放在linux系统中执行的
jvm是跨语言的平台
只要是符合jvm要求的字节码文件就能被jvm加载,例如Java,scala,jython,jruby,js等。例如spark是scala写的,但是运行环境用的是jvm。Java是可以调用scala的类的。
JVM体系架构
- 类装载器ClassLoader:用来装载.class文件 装载到内存的方法区中
- 执行引擎:执行字节码,或者执行本地方法
- 运行时数据区(重点):
java代码执行流程:java程序--(编译javac)-->字节码文件.class-->类装载子系统化身为反射类Class--->运行时数据区--->(解释执行)-->操作系统(Win,Linux,Mac JVM)
JVM的生命周期
jvm的启动:java虚拟机的启动是通过引导类加载器(bootstrap class loader)创建一个初始类(initial class)来完成的,这个类是由虚拟机的具体实现指定的。
虚拟机的执行:执行一个所谓的java程序的时候,真正执行的是一个叫做java虚拟机的进程
虚拟机的退出:
- 程序正常执行结束
- 程序执行过程中遇到异常或者错误而异常终止的
- 由于操作系统出现错误而导致java虚拟机进程终止
- 某线程调用Runtime类或System类的exit方法等方式来退出
- 等等
结语
这边文章只是针对于jvm的概述,后续的类加载机制,5个运行时数据区详解,GC等等都会在公众号中。
请关注我的公众号,一起交流后端技术
本文使用 mdnice 排版