先有JVM还是先有垃圾回收器?很多人弄混淆了
是先有垃圾回收器再有JVM呢,还是先有JVM再有垃圾回收器呢?或者是先有垃圾回收再有JVM呢?历史上还真是垃圾回收更早面世,垃圾回收最早起源于1960年诞生的LISP语言,Java只是支持垃圾回收的其中一种。下面我们就来刨析刨析JVM的垃圾回收~

文章目录
- 1. 判断可回收对象
- 1.1 引用计数法
- 1.2 可达性分析算法
- 2. 垃圾回收器
- 2.1 垃圾回收区域
- 2.2 回收永久代
- 2.3 垃圾回收器
- 2.4 CMS原理
- 2.5 CMS的缺点
- 2.6 G1垃圾回收器
- 3. 垃圾回收算法
- 3.1 优化复制算法
- 未完待续。。。
1. 判断可回收对象
1.1 引用计数法
面试官:JVM为什么不采用引用计数法?
每个Java对象在引用计数法里都有一个引用计数器,引用失效则计数器 - 1,有新的引用则计数器 + 1,通过计数器的数值来判断该对象是否是可回收对象。
大家看下这个例子,如果对象A和对象B没有被任何对象引用,也没有被任何线程访问,这两个对象按理应该被回收。但如果对象A的成员变量引用了对象B,对象B的成员变量引用了对象A,它们的引用计数器数值都不为0,通过引用计数法并不能将其视为垃圾对象。
class A {B b = new B();}class B {A a = new A();}
就因为引用计数法很难解决对象之间相互循环引用的问题,所以目前JVM采用可达性分析算法来判断Java对象是否是可回收对象。
1.2 可达性分析算法
面试官:那你讲讲可达性分析算法?
可达性分析顾名思义就是以某个起始点来判断它是否可达,这个起始点称为GC Roots。如果Java对象不能从GC Roots作为起始点往下搜索到,那该对象就被视为垃圾对象,即可回收对象。

可以作为GC Roots对象一共包括以下四种,这点也是面试官常问的:
- 虚拟机栈中引用的对象。
- 本地方法栈中引用的对象。
- 方法区中类静态属性引用的对象。
- 方法区中常量引用的对象。
2. 垃圾回收器
2.1 垃圾回收区域
面试官:垃圾回收器回收的是哪个区域?
JVM由五大区域组成:堆内存、方法区、程序计数器、虚拟机栈、本地方法栈。先说结论,垃圾回收器回收的是堆内存和方法区两大区域。
程序计数器、虚拟机栈、本地方法栈的内存分配和回收都具备确定性,都是随着线程销毁而销毁,因此不需要进行回收。
但在堆内存、方法区中,内存分配和回收都是动态的,我们只有在运行期间才能知道会创建哪些对象;另外这些垃圾对象不会自动销毁,如果任由这两部分区域的垃圾对象不管,势必造成内存的浪费甚至有内存泄漏的可能。
垃圾回收器存在的意义就是通过自动检测和回收这些垃圾对象,来减少内存泄漏的风险。
2.2 回收永久代
面试官:那永久代不会进行垃圾回收对吧?
虽然永久代的垃圾回收效率是比较低的,但永久代里的废弃常量和无用的类仍然会被回收。
例如创建一个字符串常量name,该字符串会存在于常量池中。如果该字符串没有任何String对象去引用它,当发生内存回收时有必要会清除该废弃常量。
private static final String name = "JavaGetOffer";
2.3 垃圾回收器
面试官:你说说都有哪些垃圾回收器?
目前市面上共有七种垃圾回收器。
-
Serial是一个作用在新生代的单线程垃圾回收器。在垃圾回收期间系统的所有线程都会阻塞,因此垃圾回收效率也相对较高。
-
ParNew则是Serial的多线程版本。这也是第一款并发的垃圾回收器,相比Serial来说垃圾回收不需要阻塞所有线程,第一次实现了让垃圾回收线程和用户线程同时工作。
-
Serial Old是Serial的老年代版本。
-
Parallel Scavenge同样是作用在新生代且是多线程,不过它的设计目标是达到一个可控制的吞吐量。
-
Parallel Old是Parallel Scavenge收集器的老年代版本,我们可以把它和Parallel Scavenge搭配一起使用。
-
CMS是一种以最短停顿时间为目标的多线程收集器,下文我会介绍CMS实现最短停顿的原理。
-
G1收集器可以说是CMS的升级版。
我们可以根据业务实际情况来为各个年代搭配不同的垃圾回收器,以下的垃圾回收器如果有线连接,说明它们之间可以搭配使用。

2.4 CMS原理
面试官:你说的CMS为什么有较短的停顿?
CMS采用了标记-清除算法,整个运作过程分为了初始标记、并发标记、重新标记、并发清除四个阶段。
其中初始标记、重新标记的停顿时间是比较短的,而耗时最长的并发标记、并发清除能够和用户线程一起并发工作不需要停顿,可以说CMS只需要造成初始标记、重新标记带来的短时间停顿。
2.5 CMS的缺点
面试官:那它有什么缺点?
- CMS是多线程的,在垃圾回收时会占用一部分线程,可能会使系统变得相对较慢。
- CMS并发清理时用户线程还在运行着,也就是说还会有新的垃圾不断产生,这些垃圾被称为浮动垃圾。因为浮动垃圾产生在标记阶段后,很明显CMS本次收集是无法处理这些浮动垃圾的,只能等到下一次GC回收。
- CMS采用标记-清除算法,标记-清除算法的缺点是会产生空间碎片,有可能造成大对象找不到足够的连续空间而发生OOM的情况。
2.6 G1垃圾回收器
面试官:你说G1是CMS的升级版,为什么?
G1垃圾回收器设计之初被赋予的使命是未来可以替换掉JDK1.5中发布的CMS垃圾回收器。所以大家可想而知,CMS垃圾回收器的优点G1垃圾回收器都有,另外G1垃圾回收器也避免了CMS的一些不足。
- G1采用的垃圾回收算法是标记-整理算法,避免了CMS采用标记-清除可能产生的空间碎片。
- 其他收集器在新生代、老年代分别采用不同收集器进行配合,而G1垃圾回收器可以不需要其他收集器配合就能独立管理整个GC。
3. 垃圾回收算法
面试官:垃圾回收算法都有什么?
垃圾回收算法一共有四种,其中最基础的垃圾回收算法是标记-清除算法,其他算法其实都是对标记-清除算法的优化而产生的,我们继续往下看。
(1)标记-清除算法。
标记-清除算法顾名思义分为标记和清除两个阶段,首先标记出所有可回收的对象,标记完成后统一进行清除。但该算法有一个缺点,被标记和未标记的对象都是分散存储在内存中的,当清除标记对象后会出现空间碎片的情况,如下图:

(2)复制算法。
复制算法把内存划分为容量相等的两块,每次只使用一块,当这一块内存不足时就将存活的对象复制到另一块中,同时清除当前块的内存空间。这种算法实现简单且运行高效,也不会产生空间碎片的情况,因为新生代的GC是比较频繁的,所以复制算法也广泛用于新生代的垃圾回收。但缺点很明显是浪费了50%的内存空间。
(3)标记-整理算法。
标记-整理算法是对标记-清除算法的优化。该算法在内存到达一定量后,会把所有已标记的垃圾对象都向一端里移动,然后以存活对象所在的一端为边界,清除边界内所有内存,避免了标记-清除算法可能产生的空间碎片。
(4)分代收集算法。
一般实际业务系统都是采用分代收集算法。分代顾名思义把JVM内存拆分,分为了新生代、老年代,对不同年代的垃圾回收采用不同的垃圾回收算法来确保回收效率。
大家可以看下自己公司的JDK使用了什么垃圾回收器,加深下对本篇的理解。
# 打印JVM启动时的命令行标志
java -XX:+PrintCommandLineFlags -version
3.1 优化复制算法
面试官:复制算法可以怎么优化吗?
复制算法把内存划分为容量相等的两块,也就是按1:1分配内存,但这也浪费了50%空间。
可以把内存分为一块较大的Eden空间和两块较小的Survivor空间,每次只使用Eden空间和其中一块Survivor空间,而另一块Survivor空间用来保存回收时还存活的对象。这样就只浪费了其中一块Survivor空间的内存。
✨覆盖Java程序员所需掌握的Java核心知识、面试重点,本博客收录在我开源的《Java学习面试指南》中,会一直完善下去,希望收到大家的 ⭐ Star ⭐支持,这是我创作的最大动力: https://github.com/hdgaadd/JavaGetOffer
未完待续。。。
创作不易,不妨点赞、收藏、关注支持一下,各位的支持就是我创作的最大动力❤️
相关文章:
先有JVM还是先有垃圾回收器?很多人弄混淆了
是先有垃圾回收器再有JVM呢,还是先有JVM再有垃圾回收器呢?或者是先有垃圾回收再有JVM呢?历史上还真是垃圾回收更早面世,垃圾回收最早起源于1960年诞生的LISP语言,Java只是支持垃圾回收的其中一种。下面我们就来刨析刨析…...
关于 vs2019 c++20 规范里的一个全局函数 _Test_callable
(1)看名思议,觉得这个函数可以测试其形参是否是可以被调用的函数,或可调用对象? 不,这个名字不科学。有误导,故特别列出。看下其源码(该函数位于 头文件): 辅…...
07-Fortran基础--Fortran指针(Pointer)的使用
07-Fortran基础--Fortran指针Pointer的使用 0 引言1 指针(Poionter)的有关内容1.1 一般类型指针1.2 数组指针1.3 派生类(type)指针1.4 函数指针 2 可运行code 0 引言 Fortran是一种广泛使用的编程语言,特别适合科学计算和数值分析。Fortran 9…...
日期差值,
日期差值 ac代码 #include<iostream> using namespace std; int ans0; int get(int n){int mon[14]{0,31,28,31,30,31,30,31,31,30,31,30,31};ans0;int m_dayn%100;int m_month(n/100)%100;int m_year(n/10000);ansm_day;while(m_month--){//加上月数if((m_year%40&…...
GMV ES6直流变频多联空调机组室外机工作原理
GMV ES6直流变频多联空调机组室外机工作原理如下: 内机为制冷模式运行时,室外机根据室内机的运行负荷需求启动运行,室外换热器作为系统的冷凝器,各制冷室内机的换热器并联作为系统的蒸发器,通过室内机的送回风循环实现…...
中国开源 AI 大模型之光-InternLM2
今天给大家带来 AI 大模型领域的国产之光 - InternLM2,在10B量级开源大模型领域取得了全球 Top 3 的成绩,仅次于 Meta 发布的 Llama-3,在国内则是第一名的存在! 简介 InternLM2是由上海人工智能实验室和商汤科技联合研发的一款大型…...
【嵌入式开发】Arduino人机界面及接口技术:独立按键接口,矩阵按键接口,模拟量按键接口(基础知识介绍)
“生活总是让我们遍体鳞伤,但到后来,那些受伤的地方一定会变成我们最强壮的地方。” 🎯作者主页: 追光者♂🔥 🌸个人简介: 📝[1] CSDN 博客专家📝 🏆[2] 人工智能领域优质创作者🏆 🌟[3] 2022年度博客之星人工智能领域TOP4🌟 🌿[4] …...
element ui Tree树形控件
lazy 是否懒加载子节点,需与 load 方法结合使用 boolean 默认为falseload 加载子树数据的方法,仅当 lazy 属性为true 时生效 function(node, resolve)使用懒加载load不需要再使用data,利用resolve返回值即可注意:第一层的数据要写…...
AI 绘画神器 Fooocus 图生图:图像放大或变化、图像提示、图像重绘或扩充、反推提示词、生成参数提取、所需模型下载
本文收录于《AI绘画从入门到精通》专栏,专栏总目录:点这里,订阅后可阅读专栏内所有文章。 大家好,我是水滴~~ 本文讲述 Fooocus 的图生图功能,主要内容包括:图像放大或变化、图像提示、图像重绘或扩充、反推…...
yolov8 模型架构轻量化 | 极致降参数量
模型轻量化加速是深度学习领域的重要研究方向,旨在减小模型的体积和计算复杂度,从而提高在资源受限设备上的运行效率,模型参数量在轻量化加速中扮演着至关重要的角色。 首先,模型参数量直接决定了模型的复杂度和存储空间需求。随…...
uniapp 小程序低功耗蓝牙配网 ble配网 物联网
1.获取蓝牙列表 bleList.vue <template><view><button touchstart"startSearch">获取蓝牙列表</button><scroll-view :scroll-top"scrollTop" scroll-y class"content-pop"><viewclass"bluetoothItem&q…...
服务器防火墙有什么用防护策略
随着互联网的飞速发展,服务器的安全问题日益凸显。为了保护服务器免受网络攻击和恶意入侵的威胁,人们引入了防火墙的概念。服务器防火墙作为保护服务器的第一道防线,具有重要的作用。那么服务器防火墙有什么用? 首先,服…...
27.哀家要长脑子了!
目录 1.316. 去除重复字母 - 力扣(LeetCode) 2. 1209. 删除字符串中的所有相邻重复项 II - 力扣(LeetCode 哎哟 烦死了 刚刚不小心退出又没保存 又要写一遍 烦死了 最近刷题不得劲啊 感觉这脑子没长一点 1.316. 去除重复字母 - 力扣&am…...
Redis实战—验证码登录注册
目录 基于Session Controller层 Service层 ServiceImpl层 编辑校验登录状态 ThreadLocal 登录拦截器 添加拦截器到Config Controller层实现 基于Redis ServiceImpl 新增刷新拦截器 添加拦截器到Config 基于Session Controller层 /*** 发送手机验证码*/PostMappi…...
对话机器人技术解说
一、RAG介绍 如何不通过微调模型来提高LLM性能,检索增强生成(RAG)是未来的发展方向。 Embedding:将文档的句子或单词块转换为数字向量。就向量之间的距离而言,彼此相似的句子应该很近,而不同的句子应该离…...
红黑树底层封装map、set C++
目录 一、框架思考 三个问题 问题1的解决 问题2的解决: 问题3的解决: 二、泛型编程 1、仿函数的泛型编程 2、迭代器的泛型编程 3、typename: 4、/--重载 三、原码 红黑树 map set 一、框架思考 map和set都是使用红黑树底层&…...
压力给到 Google,OpenAI 发布 GPT-4o 来了
北京时间5月14日凌晨1点,OpenAI 开启了今年的第一次直播,根据官方消息,这次旨在演示 ChatGPT 和 GPT-4 的升级内容。在早些时候 Sam Altman 在 X 上已经明确,「我们一直在努力开发一些我们认为人们会喜欢的新东西,对我…...
【SpringSecurity源码】过滤器链加载流程
theme: smartblue highlight: a11y-dark 一、前言及准备 1.1 SpringSecurity过滤器链简单介绍 在Spring Security中,过滤器链(Filter Chain)是由多个过滤器(Filter)组成的,这些过滤器按照一定的顺序对进…...
第9章.Keil5-MDK软件简介
目录 0. 《STM32单片机自学教程》专栏 9.1 主界面 9.2 文本格式编辑 9.3 代码提示&语法检测&代码模版 9.4 其他小技巧 9.4.1 TAB 键的妙用 9.4.2 快速定位函数/变量被定义的地方 9.4.3 快速注释与快速消注释 9.4.4 快速打开头文件 9.4.5 查找替换…...
mysql中utf8字符集中文字节长度统计如何统计到2个字节一个汉字
在 MySQL 的 utf8 字符集中(也被称为 utf8mb3),中文字符实际上并不是用2个字节来表示的,而是使用3个字节。这是 UTF-8 编码的一个特性,它使用1到4个字节来表示一个字符,具体取决于字符的 Unicode 码点。 对…...
深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...
Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
Qt的学习(一)
1.什么是Qt Qt特指用来进行桌面应用开发(电脑上写的程序)涉及到的一套技术Qt无法开发网页前端,也不能开发移动应用。 客户端开发的重要任务:编写和用户交互的界面。一般来说和用户交互的界面,有两种典型风格&…...
Axure Rp 11 安装、汉化、授权
Axure Rp 11 安装、汉化、授权 1、前言2、汉化2.1、汉化文件下载2.2、windows汉化流程2.3、 macOs汉化流程 3、授权 1、前言 Axure Rp 11官方下载链接:https://www.axure.com/downloadthanks 2、汉化 2.1、汉化文件下载 链接: https://pan.baidu.com/s/18Clf…...
【大厂机试题解法笔记】矩阵匹配
题目 从一个 N * M(N ≤ M)的矩阵中选出 N 个数,任意两个数字不能在同一行或同一列,求选出来的 N 个数中第 K 大的数字的最小值是多少。 输入描述 输入矩阵要求:1 ≤ K ≤ N ≤ M ≤ 150 输入格式 N M K N*M矩阵 输…...
Python爬虫(52)Scrapy-Redis分布式爬虫架构实战:IP代理池深度集成与跨地域数据采集
目录 一、引言:当爬虫遭遇"地域封锁"二、背景解析:分布式爬虫的两大技术挑战1. 传统Scrapy架构的局限性2. 地域限制的三种典型表现 三、架构设计:Scrapy-Redis 代理池的协同机制1. 分布式架构拓扑图2. 核心组件协同流程 四、技术实…...
大语言模型解析
1. Input Embedding embedding:将自然语言翻译成index 每个index对应一个embedding,embedding需要训练,embedding是一个数组...
6.8 note
paxos算法_初步感知 Paxos算法保证一致性主要通过以下几个关键步骤和机制: 准备阶段 - 提议者向所有接受者发送准备请求,请求中包含一个唯一的编号。 - 接受者收到请求后,会检查编号,如果编号比它之前见过的都大,就会承…...
