Java虚拟机(JVM)
目录
- 内存区域划分
- 堆(Heap)
- 方法区(Method Area)
- 程序计数器(Program Counter Register)
- 虚拟机栈(VM Stack)
- 本地方法栈(Native Method Stack)
- 类加载的过程
- 类加载过程
- 类加载器
- 双亲委派模型
- 垃圾回收机制
- 1. 找出垃圾
- 2. 释放垃圾的内存空间
JVM(Java虚拟机)是Java Virtual Machine的缩写,是一种可以执行Java字节码的虚拟机。它为Java应用程序提供了一个与平台无关的执行环境,使得Java程序只需编写一次,就可以在安装了JVM的任何系统上运行
本文主要介绍三个部分:JVM内存区域划分、类加载的过程、垃圾回收机制
内存区域划分
运行时数据区划分如下

堆(Heap)
堆是JVM中最大的一块内存区域,主要用于存储对象实例,new出来的对象变量都是存储在栈上。堆是所有线程共享的内存区域(只有一份),并且是垃圾回收器的主要工作区域。堆内存大概分为以下几个部分:
- 新生代(Young Generation):大多数对象的生命周期都很短,因此年轻代被划分为三个部分:Eden区、Survivor0区(S0)、Survivor1区(S1)。对象通常在Eden区被创建,经过一次垃圾回收后,存活的对象会被移动到S0或S1区,每经过一次垃圾回收,存活的对象就会在S0和S1之间移动,直到晋升到老年代。
- 老年代(Old Generation):在年轻代中经历了多次垃圾回收仍然存活的对象,以及一些大对象(如大数组),会被移动到老年代。老年代的垃圾回收频率较低,因为这里存放的都是生命周期较长的对象。

方法区(Method Area)
方法区是所有线程共享的内存区域(只有一份),用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
程序计数器(Program Counter Register)
程序计数器是一块小的内存空间,它为每个线程私有。程序计数器保存了当前执行的字节码指令的地址(类似于咱们写代码时的行号)。在JVM中,字节码解释器通过改变程序计数器的值来控制执行流程。
程序计数器是程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依靠这个计数器完成。

虚拟机栈(VM Stack)
虚拟机栈也是线程私有的内存区域,它的生命周期与线程相同。虚拟机栈用于存储局部变量表、操作栈、动态链接、方法出口等信息。每个方法在执行时都会创建一个栈帧(Stack Frame),用于存储局部变量和操作数栈,当方法执行结束时,栈帧会被销毁。
-
局部变量表(Local Variables):存储方法中的局部变量。
-
操作数栈(Operand Stack):用于存储计算过程中的中间数据。
-
动态链接(Dynamic Linking):将符号引用转换为直接引用。
-
方法出口(Method Exit):用于方法正常退出或异常退出时的清理工作。
本地方法栈(Native Method Stack)
本地方法栈与虚拟机栈类似,Java虚拟机栈是给JVM使用的,而本地方法栈是给本地方法使用的。
提问:下面变量(a、b、c、d、e、f)属于哪个内存区域?
class Test {private int a;private Test b = new Test();private static int c;private static Test d = new Test();public static void main(String[] args) {int e = 1;Test f = new Test();}
}
答:a、b属于堆,c、d属于方法区,e、f属于栈
变量属于哪个区和变量是否为内置类型无关
局部变量==>栈
成员变量==>堆
静态成员变量==>方法区
类加载的过程
JVM类加载是Java程序运行的基础,它涉及将类的.class文件从磁盘加载到内存中,并进行校验、链接和初始化等一系列步骤。
类加载过程
-
加载(Loading):
-
类加载过程的第一步,JVM通过类的全限定名获取其定义这个类的二进制字节流(例如,从.class文件、JAR文件或者网络中获取)。
-
将这个字节流所代表的静态存储结构转化为JVM内部运行时的数据结构。
-
在内存中创建一个代表该类的
java.lang.Class对象,这个对象将作为程序访问这个类的接口。简单来说就是:根据类名找到对应的.class文件,打开文件并读取内容。
-
-
验证(Verification):
确保读取到的.class文件符合JVM规范,没有安全问题。包括文件格式验证、元数据验证、字节码验证和符号引用验证,确保类的信息是合法的,不会危害虚拟机的安全。 -
准备(Preparation):
为类对象分配内存空间,根据读取到的.class文件内容,确定类对象所需要的空间大小,申请出对应大小的空间,并设置默认初始值(通常是0)。 -
解析(Resolution):
将类、接口、字段和方法的符号引用转换为直接引用。符号引用就是类、字段、方法的全限定名,直接引用保存的是内存中的地址。 -
初始化(Initialization):
执行类的静态初始化和静态变量的赋值操作,执行类中的静态代码块。
类加载器
JVM内置了几种主要的类加载器:
-
启动类加载器(Bootstrap ClassLoader):
负责加载标准库中的类。
-
扩展类加载器(Extension ClassLoader):
负责加载扩展类。
-
应用程序类加载器(Application ClassLoader):
负责加载第三方库中的类、自己写的代码中的类。
双亲委派模型
双亲委派模型(Parent Delegation Model)是Java虚拟机(JVM)中的一种类加载机制。它的核心思想是,当一个类加载器收到类加载请求时,会先委托其父类加载器去完成这个请求,只有在父类加载器无法完成时,自己才会尝试去加载这个类。

双亲委派模型是类加载5个步骤中第一个步骤中的环节,
工作流程:通过得到的全限定名,
- 从Application ClassLoader开始进行加载,此时不会立刻扫描目录,而是把任务委派给Extension ClassLoader
- Extension ClassLoader拿到任务后,也不会立刻扫描目录,而是把任务委派给Bootstrap ClassLoader
- Bootstrap ClassLoader在目录中进行扫描加载对应的类,如果Bootstrap ClassLoader没找到对应的类,就把任务返回给Extension ClassLoader,如果找到了直接进行后续的类加载过程。类似的,如果Extension ClassLoader没找到,会继续吧任务返回给Application ClassLoader,如果Application ClassLoader找到了直接返回,如果Application ClassLoader没找到,就会抛出异常
类加载请求首先由父类加载器尝试完成,只有在父类加载器无法完成类加载时,才由子类加载器尝试自己去加载。
双亲委派模型机制就是为了防止用户自己定义的类和标准库的类名一样,把标准库的类覆盖掉。
垃圾回收机制
JVM的垃圾回收机制(Garbage Collection, GC)是Java内存管理的重要组成部分,主要目标是自动回收不再使用的对象,释放内存资源,避免内存泄漏和溢出。垃圾回收机制主要工作区域是堆。
GC是如何回收的?
1. 找出垃圾
方案1:给每个对象分配一个计数器,计数器记录的是当前有多少个变量引用了这个对象,每增加一个引用计数器就+1,每减少一个引用就-1。如果计数器为0,表示当前对象没有人引用它,说明这个对象就是垃圾。这个方案存在问题循环引用问题,并且会消耗额外的内存空间,JVM没有采用。
循环引用问题:
class Test {Test t = null;
}
//..........class Main {public static void main(String[] args) {Test a = new Test();Test b = new Test();a.t = b;b.t = a;a = null;b = null;}
}
//这两个对象引用计数器为0不能被释放,但是这两个对象又无法使用
方案2:可达性分析(JVM采用的方案)
JVM会从一组根对象(GCroot)开始,遍历所有可达对象(类似于二叉树、多叉树遍历)。如果某个对象不可通过根对象引用到达,JVM便会将其视为垃圾并回收。常见的GCroot:栈上的局部变量、方法区中的静态成员、常量池中引用指向的对象。
2. 释放垃圾的内存空间
有以下垃圾回收算法
标记-清除算法:
先标记出所有存活的对象,然后清除未被标记的对象。这种方法简单,但会产生大量内存碎片(不是连续的空间),后续申请内存的时候可能申请不了(申请的空间一定是连续的)。
复制算法:
将可用内存分为大小相等的两块,每次只使用一块,当一块用完,将存活的对象复制到另一块,然后清理已使用过的内存。这种方法解决了内存碎片问题,但代价是内存使用效率降低,复制成本比较大。
标记-整理算法:
类似于顺序表删除中间元素的操作。先标记出存活的对象,然后让所有存活的对象向一端移动,之后清理端边界以外的内存区域。这种方法解决了内存碎片问题。这种方法的代价是移动存活对象的开销比较大
分代收集算法(JVM采取的方案):
根据对象存活周期的不同,将堆分为新生代和老年代。

- 新生代(Young Generation):大多数对象的生命周期都很短,因此年轻代被划分为三个部分:Eden区、Survivor0区(S0)、Survivor1区(S1)。对象通常在Eden区被创建,经过一次垃圾回收后,存活的对象会被移动到S0或S1区,每经过一次垃圾回收,存活的对象就会在S0和S1之间移动,直到晋升到老年代。
- 老年代(Old Generation):在年轻代中经历了多次垃圾回收仍然存活的对象,以及一些大对象(如大数组),会被移动到老年代。老年代的垃圾回收频率较低,因为这里存放的都是生命周期较长的对象。
新生代中的对象生命周期短,适合使用复制算法;老年代中的对象生命周期长,适合使用标记-整理算法。
垃圾回收器
现在常见的垃圾回收器有CMS、G1
CMS(Concurrent Mark-Sweep)垃圾回收器:
减少STW(Stop The World),标记清除算法,并行处理大部分垃圾回收过程。可能产生内存碎片,老年代需要更大内存。
G1(Garbage First)垃圾回收器:
面向服务端的低延迟垃圾回收器,将堆划分为多个区域,优先回收垃圾最多的区域。并行和并发执行,适合大内存应用。
相关文章:
Java虚拟机(JVM)
目录 内存区域划分堆(Heap)方法区(Method Area)程序计数器(Program Counter Register)虚拟机栈(VM Stack)本地方法栈(Native Method Stack) 类加载的过程类加…...
MQ 架构设计原理与消息中间件详解(三)
RabbitMQ实战解决方案 RabbitMQ死信队列 死信队列产生的背景 RabbitMQ死信队列俗称,备胎队列;消息中间件因为某种原因拒收该消息后,可以转移到死信队列中存放,死信队列也可以有交换机和路由key等。 产生死信队列的原因 消息投…...
大数据新视界 --大数据大厂之 Alluxio 数据缓存系统在大数据中的应用与配置
💖💖💖亲爱的朋友们,热烈欢迎你们来到 青云交的博客!能与你们在此邂逅,我满心欢喜,深感无比荣幸。在这个瞬息万变的时代,我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…...
PHP基本语法总结
目录 输出语句 注释 数据类型(变量) 局部和全局作用域 类型比较(松散比较与严格比较) 常量 运算符 并置运算符 不等于 逻辑运算符 条件语句 数组 关联数组 数组排序 一般数组 关联数组 循环 函数 变量函数 魔…...
尚硅谷rabbitmq 2024第30-33节 死信队列 答疑
Virtual host: Type: Name: Durabiity: Arguments: Default for virtual host w ququt.normal.video Durable x-dead-letter-exchange x-dead-1etter-routing-xey x-mAx-1ength X-m在88点0也-6E1 exchange.dead.letter.vide zouting.key.dead.ietter.v 10 String String Number…...
解锁空间距离计算的多种方式-含前端、空间数据库、后端
目录 前言 一、空间数据库求解 1、PostGIS实现 二、GIS前端组件求解 1、Leaflet.js距离测算 2、Turf.js前端计算 三、后台距离计算生成 1、欧式距离 2、Haversice球面距离 3、GeoTools距离计算 4、Gdal距离生成 5、geodesy距离计算 四、成果与生成对比 1、Java不…...
Windows 开发工具使用技巧 QT使用安装和使用技巧 QT快捷键
一、QT配置 1. 安装 Qt 开发框架 1、下载 1、进入下载地址 下载地址1 (官方, 需注册账号): https://www.qt.io/download下载地址2(推荐): http://download.qt.io/http://download.qt.io/archive/qt/ (或更直接的…...
【实战教程】SpringBoot全面指南:快速上手到项目实战(SpringBoot)
文章目录 【实战教程】SpringBoot全面指南:快速上手到项目实战(SpringBoot)1. SpringBoot介绍1.1 SpringBoot简介1.2系统要求1.3 SpringBoot和SpringMVC区别1.4 SpringBoot和SpringCloud区别 2.快速入门3. Web开发3.1 静态资源访问3.2 渲染Web页面3.3 YML与Properti…...
LeetCode讲解篇之1043. 分隔数组以得到最大和
文章目录 题目描述题解思路题解代码题目链接 题目描述 题解思路 对于这题我们这么考虑,我们选择以数字的第i个元素做为分隔子数组的右边界,我们需要计算当前分隔子数组的长度为多少时能让数组[0, i]进行分隔数组的和最大 我们用数组f表示[0, i)区间内的…...
Python知识点:结合Python工具,如何使用TfidfVectorizer进行文本特征提取
开篇,先说一个好消息,截止到2025年1月1日前,翻到文末找到我,赠送定制版的开题报告和任务书,先到先得!过期不候! 如何使用Python的TfidfVectorizer进行文本特征提取 在自然语言处理(…...
Diffusion models(扩散模型) 是怎么工作的
前言 给一个提示词, Midjourney, Stable Diffusion 和 DALL-E 可以生成很好看的图片,那么它们是怎么工作的呢?它们都用了 Diffusion models(扩散模型) 这项技术。 Diffusion models 正在成为生命科学等领域的一项尖端技术&…...
查找回收站里隐藏的文件
在Windows里,每个磁盘分区都有一个隐藏的回收站Recycle, 回收站里保存着用户删除的文件、图片、视频等数据,比如,C盘的回收站为C:\RECYCLE.BIN\,D盘的的回收站为D:\RECYCLE.BIN\,E盘的的回收站为E:\RECYCLE…...
[运维]2.elasticsearch-svc连接问题
Serverless 与容器决战在即?有了弹性伸缩就不一样了 - 阿里云云原生 - 博客园 当我部署好elasticsearch的服务后,由于个人习惯,一般服务会在name里带上svc,所以我elasticsearch服务的名字是elasticsearch-svc: [root…...
Ajax面试题:(第一天)
目录 1.说一下网络模型 2.在浏览器地址栏键入URL,按下回车之后会经历以下流程: 3.什么是三次握手和四次挥手? 4.http协议和https协议的区别 1.说一下网络模型 注:各层含义按自己理解即可 2.在浏览器地址栏键入URL,…...
数据仓库拉链表
数仓拉链表是数据仓库中常用的一种数据结构,用于记录维度表中某个属性的历史变化情况。在实际应用中,数仓拉链表可以帮助企业更好地进行数据分析和决策。 数仓拉链表(Slowly Changing Dimension, SCD)是一种用于处理维表中数据变化…...
【JVM】实战篇
1、内存调优 1.1 内存溢出和内存泄漏 内存泄漏(memory leak):在Java中如果不再使用一个对象,但是该对象依然在GC ROOT的引用链上,这个对象就不会被垃圾回收器回收,这种情况就称之为内存泄漏。 内存泄漏绝…...
2024年9月30日--10月6日(ue5肉鸽结束)
按照月计划,本周把ue肉鸽游戏完成,然后进行ue5太阳系 , 剩余14节,218分钟,如果按照10分钟的视频教程1小时进行完的话,则需要22小时,分布在10月2日-10月6日之间,每天44分钟的视频教程…...
【Python游戏开发】贪吃蛇游戏demo
准备步骤 项目开发使用【Mu 编辑器】 1.新建项目,并导入游戏图片 游戏编写 1.创建场景 SIZE 15 # 每个格子的大小 WIDTH SIZE * 30 # 游戏场景总宽度 HEIGHT SIZE * 30 # 游戏场景总高度def draw():screen…...
pytorch张量基础
引言张量的基础知识 张量的概念张量的属性张量的创建张量的操作 基本运算索引和切片形状变换自动微分 基本概念停止梯度传播张量的设备管理 检查和移动张量CUDA 张量高级操作 张量的视图广播机制分块和拼接张量的复制内存优化和管理 稀疏张量内存释放应用实例 线性回归神经网络…...
深入解析LlamaIndex Workflows【下篇】:实现ReAct模式AI智能体的新方法
之前我们介绍了来自LLM开发框架LlamaIndex的新特性:Workflows,一种事件驱动、用于构建复杂AI工作流应用的新方法(参考:[深入解析LlamaIndex Workflows:构建复杂RAG与智能体工作流的新利器【上篇】]。在本篇中ÿ…...
C++_核心编程_多态案例二-制作饮品
#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
uniapp 小程序 学习(一)
利用Hbuilder 创建项目 运行到内置浏览器看效果 下载微信小程序 安装到Hbuilder 下载地址 :开发者工具默认安装 设置服务端口号 在Hbuilder中设置微信小程序 配置 找到运行设置,将微信开发者工具放入到Hbuilder中, 打开后出现 如下 bug 解…...
uniapp 实现腾讯云IM群文件上传下载功能
UniApp 集成腾讯云IM实现群文件上传下载功能全攻略 一、功能背景与技术选型 在团队协作场景中,群文件共享是核心需求之一。本文将介绍如何基于腾讯云IMCOS,在uniapp中实现: 群内文件上传/下载文件元数据管理下载进度追踪跨平台文件预览 二…...
解析两阶段提交与三阶段提交的核心差异及MySQL实现方案
引言 在分布式系统的事务处理中,如何保障跨节点数据操作的一致性始终是核心挑战。经典的两阶段提交协议(2PC)通过准备阶段与提交阶段的协调机制,以同步决策模式确保事务原子性。其改进版本三阶段提交协议(3PC…...
《信号与系统》第 6 章 信号与系统的时域和频域特性
目录 6.0 引言 6.1 傅里叶变换的模和相位表示 6.2 线性时不变系统频率响应的模和相位表示 6.2.1 线性与非线性相位 6.2.2 群时延 6.2.3 对数模和相位图 6.3 理想频率选择性滤波器的时域特性 6.4 非理想滤波器的时域和频域特性讨论 6.5 一阶与二阶连续时间系统 6.5.1 …...
CTF show 数学不及格
拿到题目先查一下壳,看一下信息 发现是一个ELF文件,64位的 用IDA Pro 64 打开这个文件 然后点击F5进行伪代码转换 可以看到有五个if判断,第一个argc ! 5这个判断并没有起太大作用,主要是下面四个if判断 根据题目…...
深入解析光敏传感技术:嵌入式仿真平台如何重塑电子工程教学
一、光敏传感技术的物理本质与系统级实现挑战 光敏电阻作为经典的光电传感器件,其工作原理根植于半导体材料的光电导效应。当入射光子能量超过材料带隙宽度时,价带电子受激发跃迁至导带,形成电子-空穴对,导致材料电导率显著提升。…...
