JVM 基础知识(基础组成 )

使用场景

  • 线上系统突然宕机,系统无法访问,甚至直接 O0M;
  • 线上系统响应速度太慢,优化系统性能过程中发现 CPU 占用过高,原因也许是因为 JVM的 GC 次数过于频繁;
  • 新项目上线,需要设置 JVM的各种参数;等

JDK / JRE / JVM

JDK

JDK 全称 ( Java Development Kit ) ,是 Java 开发工具包 ,提供javac 编译器 、jheap、jconsole等监控工具;

JRE

JRE 全称 ( Java Runtime Environment ),是 Java 运行环境 ,提供 Class Library 核心类库 + JVM

JVM

JVM 全称 ( Java Virtual Machine ),Java 虚拟机 ,用于运行 Java 应用程序。

Java 程序执行过程

编译:

通过 javac 命令。调用 JDK 编译器,将*.java 源文件编译 为***.class 字节码文件**。

执行:

调用 java 命令, 调用 JVM 虚拟机,执行 *.class 字节码文件。

Java 程序跨平台

计算机平台

**计算机平台:**CPU 处理器与操作系统构成的系统架构。

现代的电子计算机是基于二进制设计实现,所以 CPU 仅能识别 θ 与 1 这样的二进制信号。而计算机程序的本质就是 0 与 1 之间的不同组合产生的机器指令,交给CPU去执行。CPU为了能识别执行机器指令,就需要不同 CPU架构和指令集来支持。不同的厂商,设计生产的 CPU, CPU 架构和指令集也是不同的

常见的指令集主要分为:精简指令集( RISC)和复杂指令集( CIS()。

  • 复杂指令集(CISC):X86 和X64 两种 CPU 架构基于CISC复杂指令集,比如:Intel、AMD 等厂商的 CPU。
  • 精简指令集(RISC):ARM 架构的CPU基于 RISC 精简指令集,比如:Compaq 的 Alpha 、HP 的 PA-RISC、IBM 的 Power PC、Apple的M1。

在底层硬件及指令集之上,需要搭载不同的操作系统,用于支持不同的 CP U 指令集。例如:早期的MacOS 操作系统只支持 Power 系列的 CPU。最新的Macos 系统只能安装在M1 芯片的 CPU。

Java 是一种跨平台的编程语言,主要是为了让相同的 Java 应用程序代码,不用做任何修改,可以在不同计算机系统平台上正常运行,兼容各种主流操作系统+ CPU 指令集。

跨平台原因

  • 不同的平台,相同的源代码,编译的字节码是相同的,所以字节码文件可以在不同的平台"通用";
  • 不同的平台,执行字节码时,都需要各自的 JVM 虚拟机版本,用于将字节码文件翻译成当前平台可以执行的机械码指令;

静态编译器

通过 JDK 提供的静态编译器,将 Java 源文件编译成字节码文件。

编译过程包括:

  • 词法分析:通过空格分隔出源代码中的单词、操作符、控制符等信息,将其形成 token 信息流,传递给语法解析器。
  • 语法分析:将 token 信息流按照 Java 语法规则,组装成一颗语法树
  • 语义分析:对语法树进行关键字使用、类型匹配、作用域等语法检查。
  • 字节码:当语义分析完成后,可以生成字节码。

字节码

当1个 Java 源文件被编译后,就会按照 JVM 规范和字节码定义,产生1个class 字节码文件,文件内容由 10 个固定部分组成。
前 4 个字节非常特殊,红色框的 cafe babe 是詹姆斯定义的魔法数,它的作用是标志当前文件是一个字节码文件。当 JVM在进行类加载的Load 阶段时,如果没有识别到该标志,就说明文件不是字节码文件或已损坏,则无法进行加载。绿色框代表当前版本号,0x34 的十进制为 52,是JDK8的内部版本号,代表这个字节码文件基于 JDK8 编译。

剩余部分中的每个字节均代表一个字节码指令,由于每个指令的长度按照 1 个字节存

储,所以每个指令被称为字节码(Bytecode),Java 所有的字节码指令有 200 多个。

由于纯数字的字节码指令阅读比较困难,所以 JVM 在字节码指令的基础上设计了一套操作码助记符,使用特殊单词来代替对应的数字指令。

例如:

0x15 ILOAD : 读取 int 类型的局部变量

0x36 ISTORE : 保存int类型的局部变量

0x60 IADD : 执行两个 int 类型的数值加法运算

0xbb NEW : 创建对象

Oxbc NEWARRAY : 创建数组

Oxac IRETURN : 返回 int 类型结果

JVM 执行方式

JVM 以解释+编译混合模式,执行字节码文件。

  1. JVM 的执行方式以解释执行为主。执行过程中,JVM将每个字节码文件中的每个指令,通过解释器转换成当前平台可以识别的机器码,然后交给 CPU执行。

  2. 为了提高执行效率,JVM还会在运行期间,JVM通过热点代码的统计分析,识别高频的方法调用,循环体、公共模块等,当超过阈值时,JVM会基于 JIT即时编译器 (just-in-time compiler)将热点代码转换成机器码,直接交给 CPU执行,提高执行效率。

Client 模式下默认阈值是 1500 次,在 Server 模式下是 10000 次。
JVM 解释器: 程序执行的时候,解释器首先发挥作用,省去了编译器编译时间,加快

程序的执行效率。
**JIT 编译器:**在程序运行过程中,随着时间的推移,JIT 开始慢慢发挥了作用,把热点代码编译成本地代码后,以后执行相同的代码,即可直接交给 CPU 执行,带来更高的执行效率。

机器在热机状态 可以承受的负载要大于冷机状态(刚启动时) ,如果以热机状态时的流量进行切换,可能使处于冷机状态的服务器因无法承载流量而假死。所以,在生产环境中发布应用,应该以分批的方进行发布,根据机器数量划分成多个批次,每个批次的机器数大概占到整个集群的 15%。

**故障案例:**某应用在线发布新版本,采用进行分批发布,发布总批数误填写成分为两批发布。如果是热机状态,正常情况下,集群中的一半的机器可以勉强支撑负载流量,但由于刚启动的 JVM 均是解释执行,还没有进行热点代码统计和J动态编译,导致机器启动之后,当前 1/2 发布成功的服务器马上全部宕机。

类加载器

字节码必须通过类加载器,通过加载、验证、解析等校验步骤,将字节码文件中的类,加载至 JVM 的中运行时数据区,才可以执行字节码

垃圾收集器

JVM 在运行期间,通过 Garbage Collctor 垃圾收集器,定期对运行时数据区进行垃圾对象的回收,从而实现了内存自动管理。

JVM 组成结构

JVM 由类加载器、运行时数据区、JVM解释器、JIT 即时编译器、垃圾回收器、本地方法库等部分组成。

由类加载器完成字节码文件的加载验证和解析,存储至运行时数据区,并由执行引擎中的解释器,完成字节码到机器码的解释执行。同时进行热点代码的统计分析,调用 JIT 即时编译器将字节码接编译成机器码,提高执行效率。JVM运行期间的方法调、数据对象统一存放至运行时数据区。

相关推荐
无尽的大道3 小时前
Java反射原理及其性能优化
jvm·性能优化
AAA 建材批发王哥(天道酬勤)9 小时前
JVM 由多个模块组成,每个模块负责特定的功能
jvm
JavaNice哥16 小时前
1初识别jvm
jvm
涛粒子16 小时前
JVM垃圾回收详解
jvm
YUJIANYUE16 小时前
PHP将指定文件夹下多csv文件[即多表]导入到sqlite单文件
jvm·sqlite·php
逊嘘16 小时前
【Java语言】抽象类与接口
java·开发语言·jvm
鱼跃鹰飞1 天前
大厂面试真题-简单说说线程池接到新任务之后的操作流程
java·jvm·面试
王佑辉1 天前
【jvm】Major GC
jvm
阿维的博客日记1 天前
jvm学习笔记-轻量级锁内存模型
jvm·cas·轻量级锁