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
加载
加载是指将类的字节码文件从文件系统或网络中读取到内存中,并在内存中创建一个java.lang.Class对象来代表这个类。
如下图所示:
在加载阶段中,JVM会执行以下操作:
1.通过类加载器查加载类的字节码
当JVM需要使用某个类时,会首先通过类加载器查找该类的字节码数据。
2.转化为JVM内存结构
在获取类的字节码数据后,JVM会将其转化为JVM内部数据结构,包括:常量池、字段表、方法表等等。
3.为类的静态变量分配内存,并设置默认初始值
在加载阶段中,JVM会为类的静态变量分配内存,并设置默认初始值,这些静态变量包括基本类型和引用类型。
4.生成代表该类的Class对象,并存储在方法区中
在加载阶段完成后,JVM会生成一个代表该类的Class对象,并将其存储在方法区中。
验证
验证主要就是:确保加载的类符合JVM规范,不会危害JVM的安全。
如下图所示:
验证主要分为3个步骤:
1.文件格式验证
在这个阶段,JVM会验证Class文件的格式是否符合规范。
2.语义验证 在这个阶段
JVM会对字节码进行语义分析,确保代码中不会存在语法错误和语义错误。
3.字节码验证 在这个阶段
JVM会对字节码进行验证,以确保它不会对JVM的安全性产生威胁。
准备
在准备阶段,JVM会为类的静态变量分配内存,并设置默认初始值,这些静态变量包括基本类型和引用类型。
解析
解析阶段的主要任务是将类或接口中的符号引用转化为直接引用。
如下图所示:
在解析阶段中,JVM会完成以下三个任务:
1.将类或接口中的常量池中的符号引用替换为直接引用
在Java中类和接口中的常量池存储了许多符号引用,包括:类名、字段名、方法名等等。
2.解析类或接口中的父类和接口的符号引用
在解析阶段中,JVM会将类或接口中的父类和父接口的符号引用解析成直接引用,从而构建类或接口之间的继承和实现关系。
3.将字段和方法的符号引用解析成直接引用
在解析阶段中,JVM会将这些符号引用解析成直接引用,从而使得程序能够正确地访问和调用字段和方法。
初始化
初始化阶段是类加载的最后一个阶段,也是最重要的阶段之一。
在初始化阶段,JVM会为类的静态变量赋初值,并执行类的静态代码块。
如下图所示:
在初始化阶段中,JVM会执行以下操作:
1.为类的静态变量分配内存,并设置初始值
在加载阶段中,JVM会为类的静态变量分配内存,并设置默认初始值。
2.执行类的静态代码块
在初始化阶段中,JVM会执行类的静态代码块,这些静态代码块中可以包含任意的Java代码。
JVM运行时数据区
JVM运行时数据区,也叫JVM内存模型,或者JVM内存结构都可以。
会包含:JVM堆、虚拟机栈、程序计数器、Java方法区、本地方法栈等内容,如下图所示:
JVM堆
JVM堆是Java虚拟机管理的内存中最大的一块,堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old )。
如下图所示:
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方法区用于存储类信息、常量、静态变量等数据,这些数据在整个应用程序的生命周期内都是存在的。
如下图所示:
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会为该方法创建一个栈帧,并将其推入虚拟机栈的顶部。当
该方法执行完毕后,JVM会将该栈帧弹出虚拟机栈,并将控制权交给该方法的调用者。
虚拟机栈的大小是可以通过JVM的启动参数来设置的,当虚拟机栈空间不足时,JVM会抛出StackOverflowError异常。
需要注意的是,虚拟机栈存储的是基本数据类型和对象引用,而不包括对象本身,对象的存储是在堆区完成的。
本地方法栈
本地方法栈,英文全称是Native Method Stack,是JVM内存结构的组成部分,如下图所示:
本地方法栈用于执行本地方法,本地方法是用其他语言,比如: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面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》