JVM原理详解(万字图文全面解析)

JVM原理详解(万字图文全面解析)-mikechen

Java面试经常会问到JVM原理,重点会问到JVM原理的实现细节,下面我就重点来详解JVM原理@mikechen

JVM简介

JVM,全称是Java Virtual Machine,就是我们经常说的Java虚拟机,是Java程序在运行时的环境。

JVM是一个虚拟机,它能够在不同的硬件和操作系统平台上运行Java程序,并提供了一个统一的、安全的、可移植的执行环境。

 

JVM架构原理

JVM的架构主要由以下三个部分组成:

1.类加载器

负责将类文件加载到JVM中,并在必要时解析类文件。

 

2.运行时数据区

运行时数据区包括:堆、栈、方法区等。堆用于存放对象实例,栈用于存放局部变量和方法调用栈,方法区用于存放类信息、常量池等。

 

3.执行引擎

执行引擎包括:负责执行字节码指令,包括解释执行和即时编译执行。

下面我针对以上内容,我一一来详解JVM原理@mikechen

 

JVM类加载机制

JVM的类加载机制是指:JVM将字节码文件加载到内存中的过程,整个过程如下图所示:

JVM原理详解(万字图文全面解析)-mikechen

JVM类加载机制过程主要会包含:加载、验证、准备、解析、和初始化的过程,下面我一一来详解@mikechen

 

加载

加载是指将类的字节码文件从文件系统或网络中读取到内存中,并在内存中创建一个java.lang.Class对象来代表这个类。

如下图所示:

JVM原理详解(万字图文全面解析)-mikechen

在加载阶段中,JVM会执行以下操作:

1.通过类加载器查加载类的字节码

当JVM需要使用某个类时,会首先通过类加载器查找该类的字节码数据。

2.转化为JVM内存结构

在获取类的字节码数据后,JVM会将其转化为JVM内部数据结构,包括:常量池、字段表、方法表等等。

3.为类的静态变量分配内存,并设置默认初始值

在加载阶段中,JVM会为类的静态变量分配内存,并设置默认初始值,这些静态变量包括基本类型和引用类型。

4.生成代表该类的Class对象,并存储在方法区中

在加载阶段完成后,JVM会生成一个代表该类的Class对象,并将其存储在方法区中。

 

验证

验证主要就是:确保加载的类符合JVM规范,不会危害JVM的安全。

如下图所示:

JVM原理详解(万字图文全面解析)-mikechen

验证主要分为3个步骤:

1.文件格式验证 

在这个阶段,JVM会验证Class文件的格式是否符合规范。

2.语义验证 在这个阶段

JVM会对字节码进行语义分析,确保代码中不会存在语法错误和语义错误。

3.字节码验证 在这个阶段

JVM会对字节码进行验证,以确保它不会对JVM的安全性产生威胁。

 

准备

在准备阶段,JVM会为类的静态变量分配内存,并设置默认初始值,这些静态变量包括基本类型和引用类型。

 

解析

解析阶段的主要任务是将类或接口中的符号引用转化为直接引用。

如下图所示:

JVM原理详解(万字图文全面解析)-mikechen

在解析阶段中,JVM会完成以下三个任务:

1.将类或接口中的常量池中的符号引用替换为直接引用

在Java中类和接口中的常量池存储了许多符号引用,包括:类名、字段名、方法名等等。

2.解析类或接口中的父类和接口的符号引用

在解析阶段中,JVM会将类或接口中的父类和父接口的符号引用解析成直接引用,从而构建类或接口之间的继承和实现关系。

3.将字段和方法的符号引用解析成直接引用

在解析阶段中,JVM会将这些符号引用解析成直接引用,从而使得程序能够正确地访问和调用字段和方法。

 

初始化

初始化阶段是类加载的最后一个阶段,也是最重要的阶段之一。

在初始化阶段,JVM会为类的静态变量赋初值,并执行类的静态代码块。

如下图所示:

JVM原理详解(万字图文全面解析)-mikechen

在初始化阶段中,JVM会执行以下操作:

1.为类的静态变量分配内存,并设置初始值

在加载阶段中,JVM会为类的静态变量分配内存,并设置默认初始值。

2.执行类的静态代码块

在初始化阶段中,JVM会执行类的静态代码块,这些静态代码块中可以包含任意的Java代码。

 

JVM运行时数据区

JVM运行时数据区,也叫JVM内存模型,或者JVM内存结构都可以。

会包含:JVM堆虚拟机栈程序计数器Java方法区本地方法栈等内容,如下图所示:

JVM原理详解(万字图文全面解析)-mikechen

 

JVM堆

JVM堆是Java虚拟机管理的内存中最大的一块,堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old )。

如下图所示:

JVM原理详解(万字图文全面解析)-mikechen

1.新生代(Young Generation)

新生代是JVM堆的一部分,用于存储新创建的对象,新生代 ( Young ) 又被划分为三个区域:Eden、From Survivor、To Survivor。

2.老年代(Old Generation)

老年代是JVM堆的另一部分,用于存储已经存活了一段时间的对象,老年代的空间通常比新生代大,并且包含更多的对象。

3.永久代(PermGen)

永久代是JVM堆的另一个组成部分,用于存储类的元数据和静态数据。

4.元空间(Metaspace)

在JDK 8之后,永久代已经被Metaspace取代,Metaspace是一块与堆独立的内存空间,用于存储类的元数据和静态数据。

 

Java方法区

Java方法区,英文全称是Method Area,是JVM内存中的一个重要区域。

Java方法区用于存储类信息、常量、静态变量等数据,这些数据在整个应用程序的生命周期内都是存在的。

如下图所示:

JVM原理详解(万字图文全面解析)-mikechen

1.类型信息

类数据主要包括:类名、访问修饰符、父类名、接口列表、字段数据、方法数据和注解信息等。

 

2.域信息成员变量

比如:public, private,protected,static,final, volatile, transient等等。

 

3.方法数据

比如:方法的修饰符:public, private,protected,static, final,synchronized,abstract等;

 

4.运行时常量池(Runtime Constant Pool)

运行时常量池存放类中的常量,包括:字符串、final修饰的常量等。

 

虚拟机栈

虚拟机栈,英文全称Java Virtual Machine Stack。

虚拟机栈由多个栈帧(Stack Frame)组成,每个栈帧对应一个方法的执行。

如下图所示:

JVM原理详解(万字图文全面解析)-mikechen

当一个方法被调用时,JVM会为该方法创建一个栈帧,并将其推入虚拟机栈的顶部。当

该方法执行完毕后,JVM会将该栈帧弹出虚拟机栈,并将控制权交给该方法的调用者。

虚拟机栈的大小是可以通过JVM的启动参数来设置的,当虚拟机栈空间不足时,JVM会抛出StackOverflowError异常。

需要注意的是,虚拟机栈存储的是基本数据类型和对象引用,而不包括对象本身,对象的存储是在堆区完成的。

 

本地方法栈

本地方法栈,英文全称是Native Method Stack,是JVM内存结构的组成部分,如下图所示:

JVM原理详解(万字图文全面解析)-mikechen

本地方法栈用于执行本地方法,本地方法是用其他语言,比如:C/C++编写的方法,在Java程序中通过JNI(Java Native Interface)来调用。

 

程序计数器

程序计数器,英文名Program Counter,是一种专门用来存储当前正在执行的指令地址的寄存器,它保证了指令的顺序执行和分支指令的正确执行。

Java编程里的:分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。

 

JVM执行引擎

JVM执行引擎是Java虚拟机中的一部分,它负责将Java字节码转换为机器指令,并执行这些指令。

JVM执行引擎可以分为两个部分:解释器和即时编译器。

1.解释器

JVM解释器作用是解释执行Java字节码,将字节码转化为机器指令执行。

Java程序在运行时,首先需要将源代码编译成Java字节码,然后通过JVM解释器将字节码解释执行。

JVM解释器会逐条解释Java字节码指令,并将其转化为机器指令执行。

解释器的优点是可以实现跨平台执行,因为它不依赖于特定的硬件和操作系统,而是通过JVM来提供平台无关性。

 

2.即时编译器

JVM即时编译器,全称Just-In-Time Compiler,作用是将Java字节码实时编译成本地机器码,从而提高Java程序的执行效率。

JIT编译器通过将热点代码(被多次执行的代码)编译成本地机器码,使得这部分代码的执行速度比解释执行快得多。

以上就是JVM原理的详解,更多JVM内容请查看:JVM(Java虚拟机)从0到1全部合集

陈睿mikechen

10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。

关注「mikechen」公众号,获取更多技术干货!

后台回复面试即可获取《史上最全阿里Java面试题总结》,后台回复架构,即可获取《阿里架构师进阶专题全部合集

评论交流
    说说你的看法