目录
一、JVM是什么
1、概述
关于JVM,在百度上的解释为:JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。
简单地说,JVM是《JVM虚拟机规范》中提出来的规范,并不是具体实现,相当于“接口”,而真正实现他的是形如HotSport的“实现类”。
从百度的定义来看,我们可以发现:JVM并不是只为Java语言服务,而是针对字节码文件,只要是字节码文件,JVM就支持。
像java语言自不必说,还有大数据开发常用的Scala语言,Groovy语言,python等其他语言经过处理也可以转换成字节码文件,从而在JVM环境中运行。
二、为什么要用JVM
1、java程序的执行流程
程序执行的方式一般有三种,包括静态编译执行、动态编译执行、动态解释执行。编译指的是将程序编译成可让操作系统直接执行的机器码。在java语言中,程序的执行方式是以动态解释为主,动态编译为辅(静态编译执行类似C语言,编译成可执行文件(windows一般是exe,Linux一般为sh),里面存的都是机器码)。
1.1字节码与机器码的区别:
机器码:是CPU直接读取的机器指令,运行速度非常快。
字节码:一种中间状态的二进制文件,需要直译器转译后才能变成机器码。
1.2执行流程图:
如上图得出一个结论:java程序编译成的字节码文件可以做到一次编译到处使用,字节码不分操作系统,而不同的操作系统的JVM是不同的,所以只要是字节码,就能在不同的平台由不同的JVM解释成为机器码进行运行使用,所以为什么jdk的下载区分操作系统,这也体现了java语言的(.class字节码文件)强大的跨平台性和可移植性。。
1.3JDK、KRE、JVM之间的关系
JDK主要包括了编译器等开发工具和JRE两部分,JRE包含了JVM和运行类库。
有关OpenJDK和OracleJDK的区别
在命令行中使用命令 java -version 通过查看结果进行区分
①若为下图所示:
则表示该JDK为OracleJDK,其中HotSpot为JVM的实现,HotSpot为JVM规范的商用产品,除此之外还有Oracle JRockit、IBM的J9;Server为该JVM的运行模式,JVM有两种运行模式,分别为Client模式和Server模式;对于这两种模式,他们是互补的关系,区别在于Client模式启动速度较快,Server模式启动较慢; 但是启动进入稳定期长期运行之后Server模式的程序运行速度比Client要快很多。 因为Server模式启动的JVM采用的是重量级的虚拟机,对程序进行了更多的优化;而Client模式启动的JVM采用的是轻量级的虚拟机。所以Server启动慢,但稳定后速度比Client远远要快。
②若结果为
2、JVM的架构
![](https://i-blog.csdnimg.cn/blog_migrate/85c07f32f5cd3a3ae1575eba8979ec9b.png)
2.1基于JVM架构的JVM程序执行流程:
首先,由java编译器(javac)将java源代码.java文件编译成为java字节码.class文件,该字节码文件可能存在于网络、内存、硬盘等地方,而JVM都有方式可以将其加载到类装载器中,进行字节码验证等操作,若为非法字节码文件,则会被丢弃,之后再通过对于热点代码的判断,在java解释器和即时编译器之间进行协调选择执行,然后转换成操作系统可识别的机器码运行程序。
2.2java解释器和编译器(JIT)之间的协调配合流程:
在一些商用JVM实现中(这里举例HotSpot) ,字节码转换为机器码的操作最初是由解释器interpretor执行的,但是当一个代码或者代码块执行的次数(如一个方法的频繁调用和循环体的多次执行)很多时,如果每次都进行解释,那么对于空间会造成浪费和拥挤,也会降低JVM的性能,导致程序的执行缓慢,而JIT(Just In Time Compiler)很好的解决了这个问题,在JIT中(参照上图的JVM架构图),探测器检测并判断哪些代码为热点代码,并标记,然后将他们编译成与本地平台相关的机器码,并进行代码的优化,提高了程序执行的效率;JIT是属于在运行时进行编译的动态编译,这种编译方市因为编译发生在方法执行过程之中,因此形象的称为栈上替换(On Stack Replacement,OSR),即方法栈帧还在栈上,方法就被替换 了。
2.3热点代码的探测有两种方式,分别是基于采样的热点探测和基于计数器的热点探测。
- 基于采样的热点探测:虚拟机会周期性地检查各个线程的栈顶,如果发现某些方法经常出现在栈顶,那这个方法就是“热点方法”。这种探测方法的好处是实现简单高效,还可以很容易地获取方法调用关系(将调用堆栈展开即可),缺点是难以精确地确认一个方法的热度,容易因为受到线程阻塞或别的 外界因素的影响而扰乱热点探测。
- 基于计数器的热带探测:虚拟机会为每个方法(甚至是代码块)建立计数器,统计方法的执行次数,如果执行次数超过一定的阀值(通常情况下为10000次,也可以自定义),就认为它是“热点方法”。这种统计方法实现复杂一些,需要为每个方法建立并维护计数器,而且不能直接获取到方法的调用关系,但是它的统计结果相对更加精确严谨。