秋招Day11 - JVM - 垃圾回收

article/2025/8/24 20:39:21

 讲讲JVM的垃圾回收机制

垃圾回收是指JVM对内存中已经死亡的,不再使用的对象进行清除或回收。

常见的垃圾回收算法有标记-复制,标记-整理,标记-清除,分代收集算法等

一般的垃圾回收。过程是先使用可达性分析算法得出内存中哪些对象是不可达的,然后对存活对象进行标记,清除不可达对象,然后进行内存的压缩/整理。

如何判断对象是否存活?

可达性分析算法,通过一组名为GC root的根对象进行递归扫描,无法从根对象到达的对象就是垃圾。G1,GMS等主流垃圾回收器的算法。

什么是引用计数法?

每个对象都有一个引用计数器,代表有多少个引用指向它,当引用计数器为0时,可以回收。

引用计数器无法解决循环引用的问题,比如两个对象相互引用,但是没有别的对象指向他们,引用计数器也不为0,所以无法被回收。

做可达性分析前应该有哪些前置操作?

STW,Stop the World,会让所有线程在其安全点暂停,这样做是为了保证引用关系不会在垃圾回收的过程中被更改,从而导致内存错误和数据丢失

Java中可作为GC Roots的引用有哪几种

GC Roots必须是一组活跃的引用,他们是所有引用链的源头,常见的GC Roots有以下几种:

  • 虚拟机栈中的引用(引用类型的方法参数、局部变量)
  • 本地方法的JNI引用
  • 类静态final变量
  • 运行时常量池中的常量引用(String,Class)

说说虚拟机栈中的引用?
如果方法内部创建了一个引用类型的局部变量,指向一个对象,那么这个局部变量就是GC Root,其指向的对象可以从GC Root达到,方法结束后,局部变量的作用域结束,其之前指向的对象如果没有其他引用指向,就会被回收

说说本地方法栈中的JNI引用?
JNI引用就是Java本地方法中定义的指向Java对象的引用,它在本地方法执行期间保持 Java 对象活跃,可以被认为是 GC Roots。
一旦本地方法执行完毕,如果JNI引用不是全局的,那它之前指向的Java对象就会被回收(如果没有其他引用指向它)

说说类静态final变量?
静态变量属于类,定义在类中,其可以作为GC Root,其生命周期和类的生命周期一致,只要其所属的类不被垃圾回收(卸载),其就永远作为GC Root活跃,其指向的对象也永远可达。但如果其所属的类被垃圾回收(卸载),那么其生命周期也就结束,其指向的对象如果没有其他引用指向它,也会被垃圾回收。

说说运行时常量池中的常量引用?

class ConstantPoolReference {public static final String CONSTANT_STRING = "Hello, World"; // 常量,存在于运行时常量池中public static final Class<?> CONSTANT_CLASS = Object.class; // 类类型常量public static void main(String[] args) {System.out.println(CONSTANT_STRING);System.out.println(CONSTANT_CLASS.getName());}
}

运行时常量池中的常量引用有很多,比如字符串常量引用,类的直接引用(指向Class对象),static final修饰的常量的引用,这些都是GC Root。
以上代码中CONSTANT_STRING是一个常量(因为被static final修饰,而不是因为Hello World这个字符串对象本身在常量池中的常量引用),所以会被存在运行时常量池中,运行时常量池中的引用都是GC Root,所以其是一个GC Root。

CONSTAN_CLASS也是一个常量(因为被static final修饰,而不是因为Object这个class对象本身在常量池中的直接引用),所以会被存在运行时常量池中,运行时常量池中的引用都是GC Root,所以其是一个GC Root。

ConstantPoolReference类的运行时常量池:
├── CONSTANT_STRING常量引用 → "Hello, World"对象 (GC Root)
├── CONSTANT_CLASS常量引用 → Object.class对象 (GC Root)  
├── "Hello, World"字符串字面量引用 → "Hello, World"对象 (GC Root)
├── Object.class直接引用 → Object.class对象 (GC Root)
└── ...

注意:同一个对象被多个GC Root保护

这些常量引用的对象(字符串"Hello, World"和 Object.class 类对象)在常量池中,就算包含这些常量的 ConstantPoolReference 类未被卸载,这些对象也不会被垃圾回收。 

finalize了解吗?

如果对象重写了finalize方法,并且JVM判断其不可达,则会进行第一次GC,放入finalization队列,并异步执行finalize方法(finalize方法中可以使对象重新变为可达)。第二次GC会真正回收对象(如果复活则不会回收,但是下次不会再执行finalize方法)

说说分代收集算法?

新生代中采用标记-复制算法,老年代中采用的是标记-整理算法

为什么要使用分代收集算法?
因为新生代中的对象生命周期短,存活下来的也就少了,使用标记-复制算法的成本较低。老年代中存活对象数量多,使用标记-整理算法减少对象移动的开销。

标记-复制算法过程中会不会停顿?
会STW。
标记过程会停顿是为了避免对象的引用关系在标记过程中不被修改。
复制过程中会停顿是为了避免对象的内容在复制过程中被修改。

什么是Mixed GC和Full GC?

Mixed GC 是 G1 垃圾收集器特有的一种 GC 类型,它在一次 GC 中同时清理年轻代和部分老年代。

Full GC 是最彻底的垃圾收集,涉及整个 Java 堆和方法区。它是最耗时的 GC,通常在 JVM 压力很大时发生。

什么时候触发Minor GC?

当Eden区空间不足时

什么时候触发Full GC?

进行Minor GC的时候,如果JVM发现老年代没有足够的空间存放本次从新生代晋升的对象的总大小,并且老年代的最大可用的连续内存空间大小 < 历次Minor GC中从新生代进入老年代的对象大小之和的平均值(空间分配担保),说明本次 Young GC 后升入老年代的对象大小,可能超过了老年代当前可用的内存空间,就会触发 Full GC。

System.gc()jmap -dump 等命令会触发 full gc。

知道哪些垃圾收集器?

垃圾收集器可以分为分代收集器和分区收集器。分代收集器的代表是CMS,分区收集器的代表是G1和ZGC。分代收集器就是将堆内存划分为多个大小相等的区域,根据各区域的垃圾回收价值动态选择回收策略,每个Region可以是Eden、Survivor、Old或Humongous

说说Serial垃圾收集器? 

Serial是最基础的单线程垃圾收集器,进行垃圾收集时必须暂停其它所有线程的执行,仅剩一条垃圾回收线程执行(STW)

说说ParNew垃圾收集器?

Serial的多线程版本,使用多条线程进行垃圾收集

说说Parallel Scavenge垃圾收集器?

是一款新生代收集器,基于标记-复制算法实现,类似于ParNew,也能并行收集,但主要关注的是垃圾收集的吞吐量,通过自动调整Eden和Survivor的大小和比例,以及晋升阈值,最大化应用程序运行时间的占比。

说说Serial Old垃圾回收器?

是一款老年代垃圾回收器,同样是单线程的,采用标记-整理算法

说说Parallel Old收集器?

Parallel Scavenge的老年代版本,是多线程的,基于标记-整理算法

说说CMS垃圾收集器?

低延迟的老年代垃圾处理器,采用标记-清除算法,分为初始标记、并发标记、重新标记、并发清理四个过程,垃圾回收线程可以和用户线程并行运行,停顿时间短,但是容易产生内存碎片。

  1. 初始标记:标记所有从GC Roots直接可达的对象为灰色,需要STW但是很快
  2. 并发标记:从初始标记的对象出发,遍历所有对象,标记所有灰色对象引用的对象为灰色,并将原来的所有灰色对象自身标记为黑色,是并发执行的
  3. 重新标记:完成剩余的标记工作,包括处理并发阶段留下来的少量变动,需要短暂的STW
    1. 处理写屏障记录的引用变化:在并发标记阶段,应用程序可能会更新对象的引用(比如一个黑色对象新引用了一个白色对象),这些变化会通过写屏障记录下来
    2. 循环扫描灰色对象:循环遍历灰色对象,将灰色对象设为黑色,再将所有可达的白色对象设为灰色,循环执行,确保引用的对象最终都被正确的标记为黑色
    3. 清理:确保所有引用关系正确处理后,灰色对象标记为黑色,不可达的白色对象保持不变。这一步完成后,所有存活对象都应当是黑色的
  4. 并发清理:并发清理所有不可达的对象

三色标记法用于标记对象的存活状态,它将对象分为三类:

  1. 白色(White):尚未访问的对象。垃圾回收结束后,仍然为白色的对象会被认为是不可达的对象,可以回收。
  2. 灰色(Gray):已经访问到但未标记完其引用的对象。灰色对象是需要进一步处理的。
  3. 黑色(Black):已经访问到并且其所有引用对象都已经标记过。黑色对象是完全处理过的,不需要再处理。

说说G1垃圾收集器? 

属于分区收集器,将堆划为为多个相同大小的Region,面向大内存、高吞吐场景,采用标记-整理算法,避免了内存碎片,优点是停顿时间可控,适合大堆场景,但是调优困难

老年代占用率达到阈值时,Mixed GC回收过程:
并发标记:G1垃圾收集器以并发标记的方式标出老年代中的存活对象

混合收集:并发标记完成后,G1会计算出哪些区域回收价值最高(包含最多垃圾),然后优先回收这些区域,提高回收效率和减少停顿时间

可预测的停顿:用户可以设置自己预期的停顿时间,G1会尽量在这个时间内完成垃圾回收 

说说ZGC垃圾收集器?

超低延迟不固定分区大小的垃圾回收器,通过并发标记重定位来避免大部分STW操作,主要通过指针染色来管理对象状态。

  • 并发标记对象的可达性:通过对指针上增加标记位判断对象的存活状态
  • 重定位状态:对象被移动时,通过指针染色来更新对象的引用 

CMS vs G1

特性CMSG1
设计目标低停顿时间可预测的停顿时间,优先回收机制
并发性
内存碎片是,容易产生碎片否,通过区域划分和压缩减少碎片
收集代数老年代整个堆,但区分年轻代和老年代
并发阶段并发标记、并发清理并发标记、并发清理、并发回收(移动)
停顿时间预测较难预测可配置停顿时间目标

CMS 适用于对延迟敏感的应用场景,主要目标是减少停顿时间,但容易产生内存碎片。

G1 则提供了更好的停顿时间预测内存压缩能力,适用于大内存多核处理器环境。


http://www.hkcw.cn/article/JKHCdYDQHg.shtml

相关文章

Deepseek应用技巧-Dify安装和踩坑指南

前言&#xff1a;Dify的名号是非常大的&#xff0c;作为私有化AI部署中必不可少的一个组件&#xff0c;他的功能和COZE十分相似&#xff0c;可以进行工作流和智能体的搭建&#xff0c;有非常强大的功能&#xff0c;那本节就将来揭开Dify的神秘的面纱&#xff0c;首先看一下Dify…

[python] argparse怎么指定bool类型?

前述 最近在写脚本的时候想要实现一个if 操作&#xff0c;通过用户输入。确定要不要启用某个语句。 非常自然的就是使用python的argparse包&#xff0c;但是发现了一个陷阱&#xff0c;记录下。 陷阱 argparse.ArgumentParser() 可以指定输入类型&#xff0c;我可以设定为bo…

尚硅谷redis7 86 redis集群分片之3主3从集群搭建

86 redis集群分片之3主集群搭建 3主3从redis集群配置 找3台真实虚拟机,各自新建 mķdir -p /myredis/cluster 新建6个独立的redis实例服务 IP:192.168.111.175端口6381/端口6382 vim /myredis/cluster/redisCluster6381.conf bind 0.0.0.0 daemonize yes protected-mode no …

交集、差集、反选

1.交集&#xff1a;两个ROI相交的部分 dev_open_window (0, 0, 512, 512, black, WindowHandle) read_image (Image, clip) threshold (Image, Region, 0, 128) * 交集 intersection (Circle1, Circle2, RegionIntersection) 最终效果如下图所示&#xff1a; 2.差集&#xff1a…

Flutter GridView网格组件

目录 常用属性 GridView使用配置 GridView.count使用 GridView.extent使用 GridView.count Container 实现列表 GridView.extent Container 实现列表 GridView.builder使用 GridView网格布局在实际项目中用的也是非常多的&#xff0c;当我们想让可以滚动的元素使用矩阵…

The 2020 ICPC Asia Yinchuan Regional Programming Contest

A. Best Player 关于投影到坐标轴上&#xff0c;投影到x轴上&#xff0c;确实如果两个点的y值一样&#xff0c;会导致重影&#xff0c;但不能只看只看y轴的影响&#xff0c;还有要注意输出。 #include<bits/stdc.h> using namespace std; typedef long long ll; const l…

寄存器模型

8.layering sequence &#xff08;1&#xff09;概述 转化&#xff1a;高抽象级item&#xff0c;中间的sequence&#xff0c;低抽象级item。 &#xff08;2&#xff09;寄存器模型的示意图 &#xff08;3&#xff09;示例代码&#xff1a;bus packet sequence &#xff08;4&…

Python训练营打卡Day39

DAY 39 图像数据与显存 知识点回顾 1.图像数据的格式&#xff1a;灰度和彩色数据 2.模型的定义 3.显存占用的4种地方 a.模型参数梯度参数 b.优化器参数 c.数据批量所占显存 d.神经元输出中间状态 4.batchisize和训练的关系 作业&#xff1a;今日代码较少&#xff0c;理解内容…

AI预测3D新模型百十个定位预测+胆码预测+去和尾2025年5月29日第92弹

从今天开始&#xff0c;咱们还是暂时基于旧的模型进行预测&#xff0c;好了&#xff0c;废话不多说&#xff0c;按照老办法&#xff0c;重点8-9码定位&#xff0c;配合三胆下1或下2&#xff0c;杀1-2个和尾&#xff0c;再杀6-8个和值&#xff0c;可以做到100-300注左右。 (1)定…

【AI智能体】Coze 插件从使用到实战详解

目录 一、前言 二、Coze 插件介绍 2.1 什么是插件 2.1.1 插件主要功能 2.1.2 coze 插件常用类型 2.1.3 coze 插件优势 2.2 插件与工具 2.3 插件费用说明 2.4 使用限制 2.5 权限说明 2.6 coze添加插件入口 三、Coze插件创建与使用 3.1 前置准备 3.1.1 查看api列表 …

python实现一个示波器仿真,可以改参数同步效果

代码 import sys import numpy as np import matplotlib.pyplot as plt from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar from matplotlib.an…

【前端】使用grid布局封装断点式进度条

业务需求要求展示一个动态进度条&#xff0c;不同于第三方插件的进度条&#xff0c;这个ui设计的是断点式进度条&#xff0c;效果当然是美观大方&#xff0c;但是因为没有现成的第三方插件可以实现&#xff0c;这当然难不倒一个成熟的前端开发工程师。 根据ui设计可以看到进度条…

[ctfshow web入门] web78

信息收集 表面上没有任何过滤&#xff0c;自由发挥 if(isset($_GET[file])){$file $_GET[file];include($file); }else{highlight_file(__FILE__); }解题 这些解法都在web32解释过&#xff0c;不再详细解释&#xff0c;有需要点击超链接&#xff1a;[ctfshow web入门] web3…

小白的进阶之路系列之六----人工智能从初步到精通pytorch数据集与数据加载器

本文将介绍以下内容: 数据集与数据加载器 数据迁移 如何建立神经网络 数据集与数据加载器 处理数据样本的代码可能会变得混乱且难以维护;理想情况下,我们希望我们的数据集代码与模型训练代码解耦,以获得更好的可读性和模块化。PyTorch提供了两个数据原语:torch.utils…

Memory Repair (二)

Implementing BIRA and BISR Logic 本节介绍如何在 circuit 中插入 repair logic。重点是插入 BISR 逻辑。只要内存库文件中存在 RepairAnalysis 包装器&#xff0c;并且该实例的 repair_analysis_present 属性未设置为 “Off”&#xff0c;就会在内存 BIST 逻辑&#xff08;控…

Vue 3 的路由管理

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、简易路由器二、Vue Router创建路由器使用路由器创建页面前言 路由指的是通过不同 URL 访问不同页面的方式。 根据路由管辖权的归属不同,可以分为前端路由(Client-Side Routing)和后端路由(Server-Side Routing)。…

油猴脚本开发基础

1. 油猴脚本深度解析 1.1 什么是油猴脚本&#xff1f; 本质&#xff1a;基于JavaScript的浏览器扩展脚本工作原理&#xff1a;在网页加载时注入自定义JS代码核心能力&#xff1a; 修改DOM结构拦截网络请求操作浏览器API存储本地数据 应用场景&#xff1a; 广告屏蔽网页功能增…

练习:对象数组 1

定义数组存储 3 个商品对象。商品的属性&#xff1a;商品的 id&#xff0c;名字&#xff0c;价格&#xff0c;库存。创建三个商品对象&#xff0c;并把商品对象存入到数组当中。 //对象数组 1 package demo01; public class Goods {private int goodsid;private String goodsN…

Baklib知识中台驱动业务创新

知识中台构建四库体系 Baklib通过打造知识资源库、案例库、规则库及专家库四大核心模块&#xff0c;构建起企业级知识中台的底层架构。其中&#xff0c;知识资源库采用多维度标签体系对文档、报告等结构化与非结构化数据进行分类存储&#xff1b;案例库通过智能抽取技术沉淀业…

“文化人”董宇辉也学会了表演 为消费者争取福利

“文化人”董宇辉也学会了表演 为消费者争取福利。董宇辉在直播间开始“表演”与品牌商谈判的戏码。最近,他在销售某品牌电视时,商家表示要收取最高200元的安装费。董宇辉当场拒绝,表示不合理,并坚持不接受收费。最终,商家负责人现场沟通后决定为所有购买电视的朋友免费安…