JVM详解

什么是JVM

JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。
引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用Java虚拟机屏蔽了与具
体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。

Java为什么是“平台无关的编程语言”

Java虚拟机是一个可以执行Java字节码的虚拟机进程。
Java源文件被编译成能被Java虚拟机执行的字节码文件(.class文件)。
Java被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重写或者是重新编译。
Java虚拟机让这个变为可能,因为它知道底层硬件平台的指令长度和其他特性。

JRE/JDK/JVM是什么关系

JRE是Java运行环境,即(Java Runtime Environment),也就是Java平台。所有的Java程序都要在JRE下才能运行。
JDK是开发工具包,即(Java Development Kit),它是程序开发者用来编译、调试Java程序,它也是Java
程序,也需要JRE才能运行。
JVM是Java虚拟机,即(Java Virual Machine),它是JRE的一部分,一个虚构出来的计算机,它支持跨平台。

小结

Java虚拟机成为jvm,它是分离了一部分真实电脑的资源。我们写的Java程序都是在JVM上运行的,不是在真实的计算机上运行。
程序员写程序 -> JVM ->真实的计算机。
JVM解决了各操作系统兼容性问题。
目前最新版本是jdk22,使用版本一般是JDK8,JDK只有3个版本是商用免费的,即8、11、17。
JDK:开发和运行 ,其中包含了JRE,可以将.java文件 字节 为.class文件。
JRE:运行环境,其中包含JVM,运行.class文件。
JVM:通过运行.class文件去调用底层操作系统。
三种JVM:
① Sun公司的HotSpot;
② BEA公司的JRockit;
③ IBM公司的J9 JVM;
在JDK1.7及其以前我们所使用的都是Sun公司的HotSpot,但由于Sun公司和BEA公司都被oracle收购,
jdk1.8将采用Sun公司的HotSpot和BEA公司的JRockit两个JVM中精华形成jdk1.8的JVM。

JVM原理

JVM是Java核心和基础,在Java编译器和os平台之间的虚拟处理器,可以在上面执行Java的字节码程序。Java编译器主要面向JVM,生成JVM能理解的代码或字节码文件。Java源文件经编译成字节码程序,通过JVM将每一条指令翻译成不同平台的机器码,通过特定平台运行。

JVM体系结构

类加载器:加载class文件。
执行引擎:执行字节码或者执行本地方法。
运行时数据区:包括方法区、堆、Java栈、PC寄存器、本地方法栈。

JVM运行时数据区

1.类加载器(ClassLoader):在JVM启动时或者在类运行时将需要的class加载到JVM中。
2.执行引擎:负责执行class文件中包含的字节码指令
3.内存区(也叫运行时数据区)是在JVM运行的时候操作所分配的内存区。
运行时内存区主要可以划分为6个区域:
PC寄存器:用于存储每个线程下一步将执行的JVM指令。
:栈是线程私有的,每个线程创建的同时都会创建JVM栈,JVM栈中存放当前线程中的局部基本类型的变量。
:是JVM用来存储对象实例以及数组值的区域,可以认为Java中所有通过new创建的对象的内存都在此分配,Heap中的对象的内存需要等待GC进行回收。堆是JVM所有线程共享的。
方法区:存放了所加载的类信息(名称、修饰符等)、类中的静态变量、类中定义为final类型的常量、类中的Field信息、类中的方法信息;通过class对象中的getName等方法来获取信息时,实际这些数据是来源于方法区,方法区是全局共享的。
运行时常量池:存放类中固定的常量信息、方法和Field的引用信息等,其空间是从方法区中分配。
本地方法栈:JVM采用本地方法栈来支持native方法的执行,此区域用于存储每个native方法调用的状
态。

加载顺序

在这里插入图片描述
在这里插入图片描述

方法区(Method Area):用于存储类结构信息的地方,包括常量池、静态变量、构造函数等。虽然JVM规范把方法区描述为堆的一个逻辑部分, 但它却有个别名non-heap(非堆)。方法区还包含一个运行时常量池。
java堆(Heap):存储java实例或者对象的地方。这块是GC的主要区域(GC具体相关请查看之前的文章)。从存储的内容可以很容易知道,方法区和堆是被所有java线程共享的
java栈(Stack):java栈总是和线程关联在一起,每当创建一个线程时,JVM就会为这个线程创建一个对应的java栈。在这个java栈中又会包含多个栈帧,每运行一个方法就创建一个栈帧,用于存储局部变量表、操作
栈、方法返回值等。每一个方法从调用直至执行完成的过程,就对应一个栈帧在java栈中入栈到出栈的过程。所以java栈是线程私有的
程序计数器(PC Register):用于保存当前线程执行的内存地址。由于JVM程序是多线程执行的(线程轮流切换),所以为了保证线程切换回来后,还能恢复到原先状态,就需要一个独立的计数器,记录之前中断的地方,可见程序计数器也是线程私有的
本地方法栈(Native Method Stack):和java栈的作用差不多,只不过是为JVM使用到的native方法服务的。
本地方法接口:主要是调用C或C++实现的本地方法及返回结果。
扩展一个小知识:

如何判断对象是否存活

引用计数法:给对象中添加一个引用计数器,当一个地方引用了对象,计数加1;当引用失效,计数器减
1;当计数器为0表示该对象已死、可回收;但很难解决循环引用问题;
可达性分析:通过一系列称为“GC Root”的对象作为起点,从这些节点开始向下搜索,搜索所走过的路径
称为引用链,当一个对象GC Roots没有任何引用链相连,则证明此对象已死、可回收。
Java中可以作为GC Roots的对象包括:
虚拟机栈中引用的对象、本地方法栈中native方法引用的对象、方法区静态属性引用的对象、方法区常量引用的对象

总结

线程共享:方法区、堆
线程私有:java栈、本地方法栈、程序计数器
①堆空间(Heap):
存放创建出来的对象、对象中的属性,是共享的。
是Java虚拟机所管理的内存中最大的一块,在虚拟机启动时创建。线程共享,此内存区域的唯一目的就是存放
对象实例。
②方法区(Method Area):
存放方法、常量、静态变量、构造函数、字符串常量池,是共享的。
用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
③栈区(JVM Stacks):
存放局部变量、方法的调用过程(栈帧)、方法的返回值,栈中的数据会随着栈的使用结束而销毁,是线程私有,生命周期与线程相同。
虚拟机栈描述的是Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)
用于存储局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
④程序计数器(Program Counter Register):
多线程切换执行时,保证每个线程都能正常切换。
线程私有,是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器。
⑤本地方法区(Native Method Stacks):
线程私有,与虚拟机栈所发挥的作用是非常相似的,其区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native方法服务。
注: Native Method就是一个java调用非java代码的接口。

<think> 首先,用户要求了解JVM的详细解释。根据系统级指令,我需要使用中文回答,确保LaTeX语法正确,并在行内数学表达式中使用$...$格式,独立公式使用$$...$$格式。此外,我需要生成相关问题,并在引用段落末尾添加引用标识。 用户提供了几个引用: - 引用[1]:简要介绍了JVM作为Java程序运行的核心引擎,翻译字节码并管理资源。 - 引用[2]:更详细地描述了JVM作为虚拟计算机系统,包括其核心组件如字节码指令集、寄存器、栈、垃圾回收堆和方法区。 - 引用[3]:深入讨论了分代收集算法和垃圾回收器的细节,包括新生代、老年代和永久代的区别。 - 引用[4]:提到了GC cause相关的触发条件。 用户说:“我想获取关于JVM的详细解释”,并提示参考这些引用。我需要整合这些信息,提供一个全面的解释。用户还提到“请尽可能多的参考用户上一次的问题和你的回答”,但这是第一个问题,所以没有上一次的问题。我应该基于提供的引用来回答。 结构化我的回答: 1. **介绍JVM的定义和作用**:基于引用[1]和[2],解释JVM是什么,它的角色。 2. **核心组件**:基于引用[2],描述字节码指令集、寄存器、栈、垃圾回收堆和方法区。 3. **垃圾回收机制**:基于引用[3],详细解释分代收集算法、新生代、老年代、永久代,以及使用的算法如复制算法和标记清除算法。 4. **其他细节**:如执行引擎(基于栈结构),以及引用[4]提到的GC触发条件。 5. **生成相关问题**:在末尾添加相关问题,基于用户指令。 确保回答清晰、结构合理: - 开头概述JVM。 - 分段详细解释关键部分。 - 使用引用标识:[^1], [^2], [^3], [^4]。 - 生成相关问题:例如,关于JVM性能、优化、应用等。 生成的相关问题: 1. JVM的垃圾回收算法有哪些优化策略? 2. 如何配置JVM参数以改善性能? 3. JVM在不同平台上的实现差异? 4. JVM内存泄漏的常见原因及调试方法? 5. JVM在现代编程中的应用场景? 现在,编写回答: - 使用中文。 - 行内数学表达式如果有,用$...$。但在JVM解释中,可能没有数学公式,所以可能不需要。如果需要,例如在解释算法时添加。 - 独立公式:同上。 - 引用:在相关段落末尾添加。 大纲: 1. **JVM概述**:定义和基本功能。 2. **JVM架构**:组件如类加载器、运行时数据区、执行引擎。 3. **运行时数据区细节**:堆、栈、方法区;分代收集。 4. **垃圾回收**:算法、分代回收。 5. **执行引擎**:字节码执行。 6. **相关问题**。 参考引用: - [^1]在概述时使用。 - [^2]在组件描述时。 - [^3]在垃圾回收时。 - [^4]在GC触发时。 最终响应结构: - 清晰分段。 - 自然添加引用。 - 结束时添加相关问题。 </think> ### JVM详细解读 Java虚拟机(JVM)是Java程序运行的核心引擎,它作为一个虚拟的计算机系统,负责解释和执行Java字节码文件(.class文件)。JVM的核心作用是将Java字节码转换为底层硬件能理解的机器指令,并管理程序运行时的内存、线程、安全和垃圾回收等资源,确保Java跨平台兼容性[^1]。接下来,我将从JVM的架构、核心组件、执行机制和垃圾回收等方面,为您详细解释。 #### 1. **JVM架构概述** JVM遵循Java SE规范,是一个抽象的计算环境,主要由类加载器子系统、运行时数据区和执行引擎三大部分构成。类加载器负责动态加载类文件,运行时数据区存储程序和对象状态,执行引擎则处理字节码的执行。整个体系结构支持Java的“一次编写,到处运行”特性[^2]。 #### 2. **核心组件细节** - **字节码指令集和寄存器**:JVM使用基于栈的指令集,每条指令对应一个操作码(例如`iload`加载整数),寄存器用于存储线程状态和临时变量。字节码被加载后,通过解释器或即时编译器(JIT)转换为机器指令[^2]。 - **运行时数据区**:包括堆、栈、方法区等。 - **堆(Heap)**:存储所有对象实例,是垃圾回收的主要区域。堆又细分为新生代和老年代[^3]。 - **栈(Stack)**:每个线程私有,存储局部变量、操作数栈和方法调用帧。栈结构高效支持方法调用和返回[^2]。 - **方法区(Method Area)**:存储类信息、常量池、静态变量等元数据。在早期实现中称为永久代(PermGen),后被元空间(Metaspace)替代以优化内存管理[^3]。 - **执行引擎**:基于栈结构,执行字节码指令。执行引擎包括解释器(用于快速启动)和即时编译器(JIT,用于优化热点代码的执行效率)。例如,执行引擎通过栈帧管理方法调用链,确保指令的正确执行顺序[^2]。 #### 3. **垃圾回收机制** JVM采用分代收集算法,根据对象的生命周期将堆划分为不同区域,并应用不同的回收策略,以平衡性能和内存效率[^3]。 - **新生代(Young Generation)**:存放新创建的对象,特点是对象数量多但生命周期短(如临时变量)。每次垃圾回收(Minor GC)时,大量对象被回收。JVM主要使用复制算法:将存活对象复制到“存活区”(Survivor Space),并清除死亡对象。复制算法高效但需要额外空间,计算公式为 $S_{\text{eden}} + S_{\text{survivor}} \leq \text{堆大小}$,其中Eden区是初始分配区[^3]。 - **老年代(Old Generation)**:存放大对象(如缓存)和生命周期长的对象(如全局变量)。回收频率较低,采用标记清除算法:先标记所有存活对象,再清除未标记对象。该算法节省空间但可能产生内存碎片,公式表示为垃圾回收效率 $E = \frac{\text{回收对象数}}{\text{总对象数}}$[^3]。 - **永久代(PermGen)或元空间**:存储类元数据和常量。主要回收废弃常量和无用类。在Java 8后,永久代被移除,元空间使用本地内存,减少内存泄漏风险[^3]。 垃圾回收触发条件多样,包括内存不足或特定API调用。例如,当GC cause为`gclocker`且配置了`GCLockerInvokesConcurrent`参数时,会触发后台并发收集器(background collector),以减少停顿时间[^4]。 #### 4. **整体执行流程** 1. **加载**:类加载器加载.class文件。 2. **验证**:确保字节码安全。 3. **执行**:执行引擎转换字节码为机器指令。 4. **内存管理**:运行时数据区分配内存,垃圾回收器自动清理无用对象。 5. **终止**:程序结束或异常时释放资源。 JVM的这种设计实现了高可移植性和自动化内存管理,但性能优化需依赖参数调优(如堆大小设置)[^1][^2]。 JVM的复杂性源于其抽象层和多区域管理,理解这些细节有助于开发者调试性能问题和内存泄漏[^3][^4]。如果您有具体场景(如高并发应用),我可以进一步分析。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值