【JVM】深入了解Java虚拟机-------内存划分、类加载机制、垃圾回收机制
目录
什么是JVM?
内存划分:
1.堆 (共享)
2.栈 (私有)
3.元数据区(共享)
4.程序计数器(私有)
示例:
JVM 类加载
一.类加载过程
1.加载
2.验证
3.准备
4.解析
5.初始化
二.双亲委派模型
如何寻找文件?
双亲委派模型主要是为了应付以下场景:
是否可以打破双亲委派模型呢?
JVM垃圾回收机制
什么是垃圾回收(GC)?
谁是垃圾?
1.引用计数
2.可达性分析
释放垃圾策略:
1.标记-清除算法
2.复制算法
3.标记-整理算法
4.分代回收
什么是JVM?
JVM(Java Virtual Machine,Java虚拟机) 是一种虚拟化的计算机,允许在其上执行 Java 程序(以及其他由 Java 编译器编译成字节码的程序)。JVM 提供了一种跨平台的执行环境,使得开发者可以编写一次代码,并在任何安装了 JVM 的设备或操作系统上运行。这种跨平台能力通常被称为“一次编写,到处运行”的特性。
内存划分:
JVM就是Java进程,当进程一旦跑起来之后,就会从操作系统里面申请一大块内存空间
JVM就是要将这块空间进行划分成不同的区域,并且每个区域都有不同的功能作用
如下图所示:分为五块不同区间
1.堆 (共享)
堆是整个内存区域中最大的一块,放的内容就是代码new出来的对象
堆里面分为两个区域:新生代和老生代,在讲到后面GC垃圾回收机制会提到....
2.栈 (私有)
分为Java虚拟机栈和本地方法栈
Java虚拟机栈存储的是保存了方法调用关系
本地方法栈存储的是本地方法的调用关系
3.元数据区(共享)
元数据区放的是“类数据”
class Test {
.....
}
Test.class就是类对象
还存放了一些方法相关的信息
例如:类有一些方法中,每个方法都代表了一系列的“指令集合”(JVM字节码指令)
还有常量池也存放在元数据区中,
4.程序计数器(私有)
程序计数器是内存区域里面最小的一块区域,它只需要保存当前要执行的下一条指令(JVM字节码)的地址
在上述四块区域中,堆和元数据区的数据是在整个进程只有一份,每个线程都可以访问到,是大家共同可以使用的;而栈和程序计数器是每个线程中有一份,是只能每个线程跟每个线程独立的,不共同使用。
示例:
class Test {int a;Test2 t2 = new Test2();String s = "hi";static int b;} public static void main() {Test t = new Test(); }
a,t2,s,b t 都存放在哪个区域中呢?
a存放在堆
t2存储在堆 new Test2()存在在堆 并且t2指向它
s 存放在堆 但"hi"存放在元数据上 s执行它
b 是静态变量 存放在元数据上
t 是局部变量存放在栈上 但它保存了对象的首地址(在堆上)
基本判断方法:
1)局部变量在栈上2)成员变量在堆上
3)静态变量或方法都在元数据上
JVM 类加载
一.类加载过程
一个java进程启动,要将.java文件转化成.class文件,加载到内存中,才能得到‘类对象’
类加载过程有以下几个环节:
1.加载
在硬盘中,找对对应的.class文件,读取文件里面的内容
2.验证
检查.class文件里的内容,看看是否符合要求JVM的规范要求,保证这些信息运行后不会危害到JVM的自身的安全;
3.准备
给类对象分配内存(元数据区),并设置类变量的初始值,如果类里有静态变量,那么值为0 /false /null 。。。
4.解析
针对字符串常量进行初始化,把刚才.class文件里面的常量的内容放到元数据区里
5.初始化
针对类对象进行初始化(不是对对象初始化,和构造方法无关),给静态成员进行初始化,执行静态代码块
这样类对象就加载完成,后续代码可以使用这个类对象,创建实例,或者使用里面的静态成员了...
二.双亲委派模型
这个模型描述了JVM加载.class文件过程中,找文件的过程;
这个类加载中的 “双亲委派模型”出现在“加载”那个环节,根据代码中写的“全限定类名”找到对应的.class文件;
全限定类名:包名+类名 比如String -> Java.lang.String List -> java.util.List;
如何寻找文件?
JVM内置了三个类加载器 负责加载不同的类
1.启动类加载器 BookstrapClassLoader 爷爷
负责加载标准库的类
2.扩展类加载器 ExtensionClassLoader 爸爸
负责加载JVM扩展库的类
3.应用类加载器 ApplicationClassLoader 儿子
负责加载第三方库的类 和自己代码写的类
这里标注了它们之间的关系并不是类的继承之间的关系,而是通过类加载器中存在一个parent字段 可以指向他们 类似树 所有它也可以称做“父亲委派模型”/“单亲委派模型”
当子类加载器需要加载类时,它会首先将请求委托给父类加载器,直到请求最终被顶级加载器(即 BookstrapClassLoader)处理。只有在父类加载器无法处理该请求时,子类加载器才会尝试加载该类。此时,如果儿子类加载器也没有找到,最后就会抛出ClassNotFoundException
双亲委派模型主要是为了应付以下场景:
当你自己的代码中写的类,类的名称和标准库/扩展库的类发生了冲突,JVM会确保加载的类是标准库上的类,就不加载自己写的类了,如果标准库的类不能加载,那么可能整个Java进程都没法加载了;
是否可以打破双亲委派模型呢?
答案当然是可以
自己写个类加载就行。。。
JVM垃圾回收机制
什么是垃圾回收(GC)?
垃圾回收机制,是Java提供对于内存自动回收的机制;
JVM(Java虚拟机)的垃圾回收(Garbage Collection,GC)机制是 Java 运行时管理内存的重要部分。其主要目的是自动化地回收那些不再被使用的对象,从而释放内存,避免内存泄漏,提高系统的稳定性和效率。JVM 的垃圾回收机制有一套复杂的算法和流程,但也让 Java 开发者无需手动管理内存。
在GC中,最主要回收的堆上的内存
1)程序计数器:不需要额外回收,线程销毁,自然就没了
2)栈:同理,线程销毁,也就没了
3)元数据区:一般也不需要,都是加载类,不需要卸载类
4)堆: 存放的都是对象实例 GC的主力部分
GC的主要流程,找到谁是垃圾(不再使用的对象),并且给它回收。
谁是垃圾?
在一个对象中,创建的时间往往可以确定,但什么时候不再使用,却是很模糊的。在编程中,一定要确保每个对象都是有效的,可不敢提前释放;
因此,判断一个对象是否需要回收,采取的策略都是比较保守的
Test t = new Test();
使用对象,是通过引用的方式来使用的,如果没有引用这个对象,那么这个对象将在代码中肯定不能使用。
如果 t = null;
new Test() 这个对象没有引用指向了,那么它就可以是作为垃圾;
具体是怎么判断对象是否有无引用,以下会介绍俩种方法。
1.引用计数
这个不是JVM使用的方案,而是Python/PHP等语言使用的方案
Test a = new Test(); b = a;
b = null; a = null;
给对象加个引用计数器,当有地方指向它,那么计数器+1,如果引用失效时,那么计数器-1;
如果计数器为0,那么这个对象将会被当做垃圾被回收
但是有以下几个问题:
1. 消耗额外的空间,如果对象非常大还好,浪费的空间可以接受,但是你对象很小,还要额外开销内存,就会浪费很多空间;
2.存在“循环引用”的问题;
class Test {Test t; }Test a = new Test(); Test b = new Test(); a.t = b; b.t = a;
第一步:
第二步:
a = null; b = null;
此时,这俩对象互相执行对方,导致这俩个计数器都为1(但不为0,所有不是垃圾),但是外部代码也访问不到这对象;
Python/PHP它们如果检测到了循环引用就会提供了报错信息;
2.可达性分析
以一系列被称为 “GC Roots” 的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到任何一个 GC Roots 没有引用链相连时,则证明该对象是不可达的,是可以被回收的对象。
GC Roots 对象:包括虚拟机栈中引用的对象、本地方法栈中引用的对象、元数据区中类静态属性引用的对象、元数据区中常量引用的对象等。
举例:类似树形状
如果将 a.right = null;
那么 c 将会断开 ,外面将找不到c了 那个就可视为 c 和 f 都是垃圾了
由于可达性分析,需要消耗一定的时间,因此Java垃圾回收,没法做到”实时性“,周期性进行扫描(JVM提供了一组专门的负责GC的线程,不停的进行扫描工作);
释放垃圾策略:
1.标记-清除算法
这种算法存在的问题是:
- 碎片化:回收后的内存空间可能会分散,导致内存碎片化,降低内存使用效率。很难使用到连续大的内存。
- 效率问题:标记和清理过程需要扫描所有对象,性能可能较差。
2.复制算法
将内存分为大小相等的两块,每次只使用其中的一块。
释放1 3 5 保留 2 4
当这一块的内存用完了,就将还存活的对象复制到另一块内存中,然后把使用过的这块内存空间一次清除掉。
这种算法的优点是避免了内存碎片化,但缺点是需要两倍于 Eden 区的内存空间来存储对象。
3.标记-整理算法
首先标记出所有需要回收的对象,然后让所有存活的对象都向一端移动,然后直接清除掉端边界以外的内存。
类似顺序表删除中间元素
- 优点:不会产生内存碎片,提高了内存的利用率;标记和压缩的过程相对来说效率较高。
- 缺点:相对于标记 - 清除算法,增加了对象移动的开销,需要更新对象的引用地址等
4.分代回收
上述三个方案,只是铺垫,JVM中的实际方案,是综合上述的方案,更复杂的策略,分代回收(即分情况讨论,根据不同的场景/特点选择合适的方案)
新生代中的对象存活率较低,通常采用复制算法进行垃圾回收;老年代中的对象存活率较高,一般采用标记 - 清除算法或标记 - 整理算法进行垃圾回收。
新生代:又分为 Eden 区和两个 Survivor 区,比例一般为 8:1:1。
新创建的对象都在Eden区,当 Eden 区满了之后,会触发一次 GC,只有少部分对象可以活过第一轮GC
Eden区 -> Survivor区 通过复制算法(由于存活数量少,复制算法的开销也比较低,Survivor区的空间也不是很大)
Survivor区 ->另一个Survivor区 通过复制算法 每一轮GC下来,Survivor区都会淘汰一部分对象,剩下的通过复制算法进入下一个Survivor区,存活下来的对象年龄+1
Survivor区 -> 老年代 某些对象 经过多次GC 还没有变成垃圾 那么将会复制到老年代区
老年代区的对象也是需要进行GC的,但是老年代中的对象都是生命周期比较久的,因此可以减小GC的频率
相关文章:

【JVM】深入了解Java虚拟机-------内存划分、类加载机制、垃圾回收机制
目录 什么是JVM? 内存划分: 1.堆 (共享) 2.栈 (私有) 3.元数据区(共享) 4.程序计数器(私有) 示例: JVM 类加载 一.类加载过程 1.加载 2.验证 3.…...

k8s部署juicefs
操作系统k8smysqlminiojuicefs内核centos8.21.19.18.0.39RELEASE.2023-12-20T01-00-02Zv0.19.04.18.0-193.el8.x86_64 本文k8s较老采用老版本的juicefs,中间件也都是部署在k8s上。测试是否能成功创建动态pvc挂在到测试pod当中并查看到数据信息。一些偏理论知识就不多…...

【ArcGIS微课1000例】0136:制作千层饼(DEM、影像、等高线、山体阴影图层)
文章目录 一、效果展示二、数据准备三、制作过程1. 打开软件2. 制作DEM图层3. 制作影像层4. 制作TIN层5. 制作等高线层四、注意事项一、效果展示 二、数据准备 订阅专栏后,从专栏配套案例数据包中的0136.rar中获取。 1. dem 2. 影像 3. 等高线 4. tin 三、制作过程 1. 打开软…...

Ajax数据爬取
有时我们用requests 抓取页面得到的结果,可能和在浏览器中看到的不一样:在浏览器中可以看到正常显示的页面数据,而使用requests 得到的结果中并没有这些数据。这是因为 requests 获取的都是原始 HTML 文档,而浏览器中的页面是JavaScript 处理…...
快速上手大模型的对话生成
本项目使用0.5B小模型,结构和大模型别无二致,以方便在如CPU设备上快速学习和上手大模型的对话上传 #mermaid-svg-Z86hUiQZ0hg9BVji {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-Z86hUiQZ0h…...

DateTimeExtensions:一个轻量C#的开源DateTime扩展方法库
推荐一个专门为System.DateTime编写的扩展方法库。 01 项目简介 该项目主要是为System.DateTime和System.DateTimeOffset的编写的扩展方法,包括自然日期差值的文本表示(精确和人性化四舍五入)、多个时区的节假日和工作日计算。 核心扩展方…...
题解:监控屏幕调整问题
问题描述 Reca 公司生产高端显示器,其中最受欢迎的型号是 AB999。屏幕尺寸为 $x \times y$ 的比例。由于某些生产特性,屏幕参数总是整数。最终,屏幕边长比例 $x:y$ 需要适应用户的需求。 为了满足用户需求,公司需要调整屏幕尺寸…...

C语言----指针
目录 1.概念 2.格式 3.指针操作符 4.初始化 1. 将普通变量的地址赋值给指针变量 a. 将数组的首地址赋值给指针变量 b. 将指针变量里面保存的地址赋值给另一个指针变量 5.指针运算 5.1算术运算 5.2 关系运算 指针的大小 总结: 段错误 指针修饰 1. con…...

树莓派之旅-在wsl-x86-64 上进行树莓派的交叉编译
前情提要: 想把自己花里胡哨的终端丢到树莓派上去,可是树莓派算力不够,编译时间过于漫长 交叉编译 定义网上有,懒得复制了,大概就是在本机电脑上编译目标平台的可执行文件 这里的目标平台是树莓派 使用 uname -m …...

nature reviews genetics | 需要更多的针对不同种族的癌症基因组图谱研究,促进精准治疗和维护治疗公平权益
–https://doi.org/10.1038/s41576-024-00796-w Genomic landscape of cancer in racially and ethnically diverse populations 研究团队和单位 Ulrike Peters–Public Health Sciences Division, Fred Hutchinson Cancer Center Claire E. Thomas–Public Health Scienc…...

代码随想录算法训练营day18
代码随想录算法训练营 —day18 文章目录 代码随想录算法训练营前言一、530.二叉搜索树的最小绝对差递归法迭代法 二、501.二叉搜索树中的众数普通二叉树的方法递归法中序迭代法 三、 236. 二叉树的最近公共祖先递归法 总结 前言 今天是算法营的第18天,希望自己能够…...
Kafka安全优化文档:漏洞修复到安全加固
文章目录 1.1.漏洞修复1.1.1.Apache Kafka反序列化漏洞1.1.2.pm2-kafka代码执行漏洞1.1.3.Apache Kafka安全绕过漏洞1.1.4.Apache Kafka Distribution - Schema Repository跨站请求伪造漏洞1.1.5.Apache Kafka输入验证错误漏洞的补丁1.1.6.Apache Kafka信息泄露漏洞1.1.7.Apach…...
Markdown如何添加任务列表-复选框的添加
Markdown如何添加任务列表-复选框的添加 前言语法讲解使用场景及应用实例代码整和渲染结果小结其他文章快来试试吧☺️ Markdown如何添加任务列表-复选框的添加👈点击这里也可查看 前言 To-do任务列表是一种很常见的时间管理工具,它适用于工作计划&…...

基于下垂控制的构网变换器功率控制【微电网变流器】【Simulink】
目录 主要内容 理论研究 整体模型 PQ计算模块 功率控制模块 PWM反馈模块 结果一览 下载链接 主要内容 该仿真针对微电网中分布式电源接入后产生的谐波影响,除了污染网络外,还会恶化微电网变流器输出电流,为了消除谐波影响&a…...

AI定义汽车/跨域融合/整车智能,汽车智能化2.0时代新机会来了
汽车智能化2.0,产业正在发生深度变革。 一方面,AI大模型开始在多个域同步赋能智能汽车,从智能座舱到智能驾驶,再到底盘域,AI大模型正在快速推动汽车变革为超级智能体,AI定义汽车时代开始来临。 另一方面&…...

(leetcode算法题)10. 正则表达式匹配
10. 正则表达式匹配 - 力扣(LeetCode) 此题的要求一个字符串 s 和一个字符规律 p之间支持 . 和 * 的正则表达式匹配 . 匹配任意单个字符 * 匹配零个或多个前面的那一个元素 所谓匹配,是要涵盖 整个 字符串 s 的,而不是部分字符串…...

SpringCloudAlibaba实战入门之Sentinel服务降级和服务熔断(十五)
一、Sentinel概述 1、Sentinel是什么 随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。 一句话概括:sentinel即Hystrix的替代品,官网: https://sentinelguard.io/zh…...

使用爬虫技术获取网页中的半结构化数据
目录 前言1. 半结构化数据与爬虫技术简介1.1 半结构化数据的定义与特性1.2 爬虫技术的基本原理 2. 爬取半结构化数据的实现过程2.1 明确目标与准备2.2 发送HTTP请求2.3 解析网页内容2.4 动态内容的处理2.5 数据存储与清洗 3. 技术挑战与应对策略3.1 处理反爬机制3.2 提高爬取效…...
2025/1/1 路由期末复习作业二
呼呼呼祝大家元旦节快乐啦!(我顶着我超重的黑眼圈说) 昨天一个人在寝室一边吃泡面,一边看步步惊心,一边吃一边哭呜呜呜呜呜若曦为什么不和八爷在一起好好爱,就因为他不当皇帝蛮!难测最是帝王心…...

OpenCV-Python实战(13)——图像轮廓
一、找轮廓 cv2.findContours() contours,hierarchy cv2.findContours(image*,mode*,method*) contours:找到的所有轮廓数组,数组内的元素为轮廓像素点坐标。 hierarchy:轮廓间的层次关系。 image:二值图像(cv2.t…...

华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...

定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...

Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...

C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...