1. 2011年,JDK7发布,1.7u4中,开始启用新的垃圾回收器G1(但是不是默认)。
    1. 2017年,发布JDK9G1成为默认GC,代替CMS。(一般公司使用jdk8的时候,会通过参数,指定GCG1)
    1. 2018年,发布JDK11,带来了革命性ZGC,性能比较强。

虚拟机介绍

虚拟机,就是虚拟的计算机,可以执行一系列虚拟计算机指令,大体上可以分为系统虚拟机和程序虚拟机。它们运行时,都会受到虚拟机提供的资源的限制。

  • 系统虚拟机:仿真模拟系统的,比如Visual BoxVMware
  • 程序虚拟机:为执行单个计算机程序设计的,比如Java虚拟机。

JAVA虚拟机

Java虚拟机是一台执行字节码的虚拟机计算机,但是字节码不一定是由Java语言编译而成。但是只要使用这一套虚拟机规则的语言,就可以享受到跨平台,垃圾收集以及可靠的即时编译器。JVM和硬件之间没有直接的交互。

  • 一次编译,到处运行。
  • 自动内存管理
  • 自动垃圾回收

下面是ava平台文档中Java概念图的描述,可以看出javac命令在JDK中,也就是将.java文件编译成为.class文件,这个就是前端编译器,将源文件编译成为字节码。这个编译器不在JRE中,也说明了JRE不包括编译环境。

JRE和JDK都包括了JVM虚拟机。JRE是运行时环境,而JDK包含了开发环境。

JDK7 中java家族的结构组成 : https://docs.oracle.com/javase/7/docs/

JDK7 中java家族的结构组成 : https://docs.oracle.com/javase/8/docs/

JVM结构

上面的图主要包括三部分:类加载器,运行时数据区,执行引擎。

类加载器,主要是将Class文件(已经经过前端编译器编译后的字节码文件),加载到运行时数据区,生成Class对象,这个过程会设计加载,链接,初始化等过程。

运行时区域主要分为:

  • 线程私有(每个线程有一份):

    • 程序计数器:Program Count Register,线程私有,没有垃圾回收
    • 虚拟机栈:VM Stack,线程私有,没有垃圾回收
    • 本地方法栈:Native Method Stack,线程私有,没有垃圾回收
  • 线程共享:
    • 方法区:Method Area,以HotSpot为例,JDK1.8后元空间取代方法区,有垃圾回收。
    • 堆:Heap,垃圾回收最重要的地方。

执行引擎主要包括解释器和即时编译器(热点代码提前编译好,这是后端编译器),垃圾回收器。字节码文件不能直接被机器识别,所以需要执行引擎来做转换。

Java代码执行流程

Java代码变成字节码文件的过程中,其实包含了词法分析,语法分析,语法树,语义分析等一系列操作。

在执行引擎中,有JIT编译器,也就是第二次编译的过程会发生在这里,会将热点代码编译成为机器指令,是按照方法的维度,缓存起来(放在方法区),也称之为CodeCache

JVM架构模型

Java编译器主要是基于栈的指令集架构,个人觉得主要原因是可移植性决定的,JVM需要跨平台。指令集架构主要有两种:

  • 基于栈的指令集架构:一个方法相当于一个入栈的操作,执行完相当于出栈操作。
  • 基于寄存器的指令集架构

基于栈的指令集架构的特点

主要特点:

  • 设计实现简单,适用于资源受限的系统,比如机顶盒,小玩具上。
  • 避开寄存器分配难题:使用零地址指令方式分配。
  • 指令流中大部分都是零地址指令,执行过程依赖操作栈,指令集更小(零地址),编译器容易实现。
  • 不需要硬件支持,可移植性强,容易实现跨平台。

基于寄存器架构的特点

  • 典型应用是x86的二进制指令集
  • 依赖于硬件,可移植性差
  • 性能好,执行效率高
  • 更少指令执行一项操作
  • 大部分情况下,寄存器的架构,一,二,三地址指令为主,而基于栈的指令集却是以零地址指令为主。

说明:什么叫零地址指令,一地址指令,二地址指令?

零地址指令只有操作码,没有操作数。这种指令有两种情况:一是无需操作数,另一种是操作数为默认的(隐含的),默认为操作数在寄存器中,指令可直接访问寄存器。

  • 三地址指令:一般地址域中A1、A2分别确定第一、第二操作数地址,A3确定结果地址。下一条指令的地址通常由程序计数器按顺序给出。

  • 二地址指令:地址域中A1确定第一操作数地址,A2同时确定第二操作数地址和结果地址。

  • 单地址指令:地址域中A 确定第一操作数地址。固定使用某个寄存器存放第二操作数和操作结果。因而在指令中隐含了它们的地址。

  • 零地址指令:在堆栈型计算机中,操作数一般存放在下推堆栈顶的两个单元中,结果又放入栈顶,地址均被隐含,因而大多数指令只有操作码而没有地址域。

栈数据结构,一般只有入栈和出栈,所以操作的地方只有栈顶元素,所以位置是确定的,不需要地址。

例子

执行2+3的操作,如果是基于栈的计算流程:

iconst_2 // 常量2入栈
istore_1
iconst_3 // 常量3入栈
istore_2
iload_1
iload_2
iadd // 常量2,3出栈,执行相加
istore_0 // 结果5入栈

基于寄存器的计算流程:

mov eax,2   //将eax寄存器的值设置为2
add eax,3 // 将eax寄存器的值加3

从上面的例子可以看出来,基于栈的寄存器的指令更小,但是基于寄存器的指令更少。

我们可以通过一个简单程序看一下:

public class StackStructTest {
public static void main(String[] args) {
int i = 2 + 3;
}
}

编译后,切换到class目录下,使用命令反编译:

java -v StackStructTest.class

看到字节码的模块,可以看到前面有iconst_5,其实5就是2+3的结果,也就是编译期间就会直接把2+3变成5,不会在运行的时候才去计算,这个是因为23都是常量。

这个现象称之为编译期的常量折叠

但是如果我们把代码成下面这种情况呢?

        int i = 2;
int j = 3;
int k = i + j;

反编译出来的指令:

const意思是constant(常量),storestoreage寄存器。

 stack=2, locals=4, args_size=1
0: iconst_2 // 2是个常量
1: istore_1 // 2加载到1号操作数栈
2: iconst_3 // 3是一个产量
3: istore_2 // 3加载到2号操作数栈
4: iload_1 // 将1号操作数栈取出,加载进来
5: iload_2 // 将2号操作数栈取出,加载进来
6: iadd // 两者相加
7: istore_3 // 结果存储到索引为3号操作数栈中
8: return

也就是栈架构的JVM,需要 8 条指令才能完成上面的变量相加计算。

栈架构总结

由于跨平台特性,Java指令基于栈来设计,因为不同的CPU架构不同,优点是跨平台,指令集小,编译器容易实现。缺点是性能下降,实现同样功能需要更多指令。

【作者简介】

秦怀,公众号【秦怀杂货店】作者,技术之路不在一时,山高水长,纵使缓慢,驰而不息。个人写作方向:Java源码解析,JDBC,Mybatis,Spring,redis,分布式,剑指Offer,LeetCode等,认真写好每一篇文章,不喜欢标题党,不喜欢花里胡哨,大多写系列文章,不能保证我写的都完全正确,但是我保证所写的均经过实践或者查找资料。遗漏或者错误之处,还望指正。

2020年我写了什么?

开源编程笔记

JVM笔记 -- JVM的发展以及基于栈的指令集架构的更多相关文章

  1. 基于栈的指令集与基于寄存器的指令集的区别,JVM指令集实例

    现代JVM在执行Java代码的时候,通常都会将解释执行与编译执行两者结合起来 所谓解释执行,就是通过解释器来读取字节码,遇到相应的指令就去执行该指令. 所谓编译执行,就是通过即时编译器(Just In ...

  2. 基于栈的指令集与基于寄存器的指令集详细比对及JVM执行栈指令集实例剖析

    基于栈的指令集与基于寄存器的指令集详细比对: 这次来学习一些新的概念:关于Java字节码的解释执行的一种方式,当然啦是一些纯理论的东东,但很重要,在之后会有详细的实验来对理论进行巩固滴,下面来了解一下 ...

  3. JVM笔记 -- JVM经历了什么?

    Sun Classic VM 世界上第一款商用 Java 虚拟机,JDK1.4 已经淘汰. 内部只有解释器,可以自己外挂JIT编译器,但是二者只能使用其一,不能配合工作. hotspot 内置了该虚拟 ...

  4. JVM笔记 -- JVM的生命周期介绍

    Github仓库地址:https://github.com/Damaer/JvmNote 文档地址:https://damaer.github.io/JvmNote/ JVM生命周期 启动 执行 退出 ...

  5. Dubbo入门到精通学习笔记(七):基于Dubbo的分布式系统架构介绍(以第三方支付系统架构为例)、消息中间件的作用介绍

    文章目录 架构简单介绍 消息中间件在分布式系统中的作用介绍 消息中间件的定义 消息中间件的作用 应用场景 JMS(Java Message Service) JMS消息模型 实现了JMS规范的消息中间 ...

  6. jvm 字节码执行 (二)动态类型支持与基于栈的字节码解释执行

    动态类型语言 动态类型语言的关键特征是它的类型检查的主体过程是在运行期而不是编译期. 举例子解释“类型检查”,例如代码: obj.println("hello world"); 假 ...

  7. 读书笔记-JVM

    局部变量表(虚拟机栈中的一部分)在编译期完成分配,运行期不会再改变大小: 每个方法对应一个栈帧(存储局部变量表.操作数栈.动态链接.方法出口等),栈帧被存储到虚拟机栈中,每个线程对应一个虚拟机栈,方法 ...

  8. JVM解毒——JVM与Java体系结构

    你是否也遇到过这些问题? 运行线上系统突然卡死,系统无法访问,甚至直接OOM 想解决线上JVM GC问题,但却无从下手 新项目上线,对各种JVM参数设置一脸懵逼,直接默认,然后就JJ了 每次面试都要重 ...

  9. 【JVM】肝了一周,吐血整理出这份超硬核的JVM笔记(升级版)!!

    写在前面 最近,一直有小伙伴让我整理下关于JVM的知识,经过十几天的收集与整理,初版算是整理出来了.希望对大家有所帮助. JDK 是什么? JDK 是用于支持 Java 程序开发的最小环境. Java ...

随机推荐

  1. hdu 1045 Fire Net 二分图匹配 && HDU-1281-棋盘游戏

    题意:任意两个个'车'不能出现在同一行或同一列,当然如果他们中间有墙的话那就没有什么事,问最多能放多少个'车' 代码+注释: 1 //二分图最大匹配问题 2 //难点在建图方面,如果这个图里面一道墙也 ...

  2. 仿ATM程序软件

    一.目标: ATM仿真软件 1 系统的基本功能 ATM的管理系统其基本功能如下:密码验证机制:吞锁卡机制:存取款功能:账户查询功能:转账功能等. 要求 要能提供以下几个基本功能: (1)系统内的相关信 ...

  3. 记一次基于springboot+aop实现日志记录实战

    1. 为什么要记录日志 好处: a. 可以对一些重要功能进行记录,方便以后跟踪是谁操作此功能的. b. 在操作某些功能时可能会发生异常,但每次出现异常我们想定位日志都要去服务器查看我们的日志.有了日志 ...

  4. windows安装

    1.windows系统版本分类a. 个人版windows98.XP.win7,win8,win10b. 企业版/服务器版windows server NT/2000/2003/2008/2012[广泛 ...

  5. Shell 函数 & 数组

    Shell 函数 函数介绍 # 什么是函数? 具备某一功能的工具 => 函数 事先准备工具的过程 => 函数的定义 遇到应用场景拿来就用 => 函数的调用 # 为何要用函数? 没有引 ...

  6. 加密后的程序在Win8中无法运行

    需要使用dotNET_Reactor 4.7以上的版本加密后才能在Win8中使用.

  7. hdu-6237

    A Simple Stone Game Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Ot ...

  8. 问题记录 java.lang.NoClassDefFoundError: org/dom4j/DocumentException

    客户端调webservice服务产生以下错误 AxisFault faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.genera ...

  9. Ubuntu16安装chrome

    不免让您失望, 安装正常的chrome,Dependency is not satisfiable: libnss3 (>= 2:3.22)问题一直没能解决,故使用chromium次而代之. s ...

  10. set CSS style in js solutions All In One

    set CSS style in js solutions All In One css in js set each style property separately See the Pen se ...