【后端面经-Java】JVM垃圾回收机制

news2024/10/7 6:50:25

【后端面经-Java】JVM垃圾回收机制

    • 1. Where:回收哪里的东西?——JVM内存分配
    • 2. Which:内存对象中谁会被回收?——GC分代思想
      • 2.1 年轻代/老年代/永久代
      • 2.2 内存细分
    • 3. When:什么时候回收垃圾?——GC触发条件
    • 4. Why:凭什么说它是垃圾?——垃圾判断算法
      • 4.1 引用计数法
      • 4.2 可达性分析法
    • 5. How:如何对待垃圾?——垃圾回收算法
      • 5.0 垃圾的垂死挣扎
      • 5.1 标记-清除算法
      • 5.2 标记-整理算法
      • 5.3 复制算法
      • 5.4 分代收集算法
    • 6. Who:谁去处理垃圾?——垃圾回收器
      • 6.1 年轻代-Serial收集器
      • 6.2 年轻代-ParNew收集器
      • 6.3 年轻代-Parallel Scavenge收集器
      • 6.4 老年代-SerialOld收集器
      • 6.5 老年代-ParallelOld收集器
      • 6.6 老年代-CMS(Concurrent Mark Sweep)收集器
      • 6.7 年轻代和老年代-G1(Garbage First)收集器
      • 6.8 垃圾回收器对比图
    • 面试模拟
    • 参考资料

1. Where:回收哪里的东西?——JVM内存分配

JVM垃圾回收机制(Garbage Collect,简称GC)主要负责回收JVM内存当中未被及时释放回收的内存区域,JVM垃圾回收机制让程序员摆脱了手动释放内存的操作,降低了程序员疏忽大意导致的风险。
那么,垃圾回收机制到底针对哪一块的内存空间进行处理呢?是整体内存还是某一块内存?
在回答这个问题之前,我们需要先了解一下JVM内存分配机制,JVM内存分配机制主要有如下几个区域:

  • 栈(Stack)
  • 堆(Heap)
  • 方法区(Method Area)
  • 本地方法栈(Native Method Stack)
  • 程序计数器(PC)
    我们需要知道的是,栈、本地方法栈、程序计数器和方法调用有关,是线程私有的,随着方法结束,栈和本地方法栈的栈帧会出栈,释放内存,因此,这三部分并不需要使用垃圾回收机制。
    而堆主要存放对象实例和数组,而方法区存放类的信息、编译信息、常量池等,这两块区域由于是线程共享的,在方法调用结束之后也不会被释放内存(毕竟A用完了,不知道B、C、D会不会用到这部分)需要使用垃圾回收机制进行内存回收。

关于每个区域的具体内容,可参考博客:【后端面经-Java】JVM内存分区详解

因此,内存回收机制主要针对堆和方法区进行处理。

2. Which:内存对象中谁会被回收?——GC分代思想

2.1 年轻代/老年代/永久代

JVM垃圾回收机制中,一般都是基于GC分代思想进行算法设计。
GC机制将内存内容分为三部分:

  • 年轻代(Young Generation):新产生的实例基本上都处于这代,因为新产生的实例大部分都是一次性的,因此这部分内存需要经常进行内存回收;
  • 老年代(Old Generation):在新生代残酷频繁的筛选机制中,多次存活下来的实例会进入老年代,老年代意味着生命周期较长,一般在内存没有满之前不会对这部分内存进行回收;
  • 永久代(Permanent Generation,JCK1.8之后改成元空间(Metaspace)):永久代存放的是JVM程序运行相关的元数据,比如类信息、方法信息、常量池等,内容重要且占空间小,因此基本上不会进行垃圾回收。

如果要类比的话,年轻代就是刚刚步入职场的小青年,不稳定性较高,很容易被裁员(垃圾回收),而熬过这个阶段,成为技术骨干(老年代)之后,基本上不会在正常公司运行过程中被裁员,除非公司倒闭(内存已满),而永久代或者元空间就是公司最高层的管理人员,对公司的运行起着关键作用,一般情况下不会被裁员。

2.2 内存细分

  1. 堆和方法区
    堆中存放年轻代和老年代,而方法区中存放永久代。
  2. 新生代区域细分
    新生代区域又分为Eden区Survivor0区Survivor1区,比例为8:1:1

整体内存细分情况如图所示:
在这里插入图片描述

3. When:什么时候回收垃圾?——GC触发条件

GC按照触发条件,可分为Scavenge GCFull GC

  • Scavenge GC(Minor GC)
    Scavenge GC是指年轻代Eden区的垃圾回收,触发条件为:
    • 年轻代Eden区域内存不足
      • 调用Scavenge GC之后,将未清理的元素放入Survivor0区域。如果Survivor0区域内存不足,则将Survivor0区域内存中的所有元素放入Survivor1区域。清空Survivor0区域,然后将Survivor1中的元素放入Survivor0中;
      • 如果Survivor1区域内存不足,则将Survivor1区域内存中的所有元素放入老年代中;
      • 如果老年代也内存不足,则会考虑触发Full GC。
  • Full GC(Major GC)
    Full GC是整体对内存的垃圾回收,包括年轻代和老年代,触发条件为:
    • 老年代内存不足
    • 永久代内存不足
    • 显性调用system.gc()
    • 上次GC之后堆内存的划分出现变化

对于GC线程,其本身的优先级比较低,因此在CPU空闲的时候,可能会进行GC处理,而在忙时基本上不会进行GC处理,除非此时内存空间不足,需要GC处理之后才能正常运行。
Full GC对于计算资源是一个很大的消耗,应该尽量避免使用Full GC。

4. Why:凭什么说它是垃圾?——垃圾判断算法

前面主要介绍了JVM垃圾回收机制的针对对象,GC分代思想和触发条件。那么,好好的一个对象实例,GC机制空口无凭凭什么说它是垃圾呢?这就需要垃圾判断算法了。
常见的垃圾判断方法有两种:引用计数法可达性分析法

4.1 引用计数法

  • 每个对象实例都有一个引用计数器,当有一个引用指向该对象实例时,引用计数器加1,当引用失效时,引用计数器减1,当引用计数器为0时,该对象实例就是垃圾,需要进行回收。
  • 补充一下JVM的引用类型,如下图所示:
  • 优点:判断逻辑简单;
  • 缺点:无法解决循环引用的问题(从图论角度来说就是环状节点无法识别)。

4.2 可达性分析法

  • 将每个实例看作节点,两个实例之间的引用关系看作路径。从GC Roots开始,对堆内存中的对象进行遍历,如果某个对象实例没有被遍历到,则说明该对象实例不可达,不可达则是垃圾,对其进行垃圾标记,等待后续回收(非连通图查找连通子图的数量)。
  • GC Roots指的是正在运行的程序中一些基本对象,从这些对象往下查找其引用对象,包括如下几种:
    • 虚拟机栈(栈帧中的本地变量表)中引用的对象
    • 方法区中类静态属性引用的对象
    • 方法区中常量引用的对象
    • 本地方法栈中JNI(Native方法)引用的对象
  • 优点:能有效解决循环引用的问题;
  • 缺点:判断逻辑复杂,需要遍历整个内存空间,效率较低。

5. How:如何对待垃圾?——垃圾回收算法

常见的垃圾回收算法包括:标记-清除算法标记-整理算法复制算法分代收集算法(自适应算法)。

5.0 垃圾的垂死挣扎

在被处决之前,垃圾会进行一次垂死挣扎,实例第一次被标记为垃圾之后,如果可以进行一次有效finalize()方法调用,和其他实例建立引用,那么该实例就会被复活,不会被回收。

5.1 标记-清除算法

在垃圾判断算法执行完成后,已经被明确判断成垃圾的实例,清除法在原地释放其内存空间,将其标记为可用空间,等待后续的内存分配。

  • 优点:操作简单,原地清除不需要复制内存
  • 缺点:会产生内存碎片,长期运行会影响CPU运行效率

5.2 标记-整理算法

标记-整理算法在标记完成之后,将所有存活的实例移动到一端,然后清除掉另一端的内存空间,这样就可以有效解决内存碎片的问题。

  • 优点:无内存碎片;
  • 缺点:需要移动实例,效率较低;

5.3 复制算法

复制算法将内存空间分为两块,每次只使用其中一块,当一块内存空间内存满了之后,将存活的实例复制到另一块内存空间中,然后清除掉之前的内存空间。

  • 优点:无内存碎片,操作简单;标记和复制可并行;
  • 缺点:可用内存空间直接减半,内存利用率较低;

5.4 分代收集算法

针对不同代的数据特点,使用不同的垃圾回收算法。

  • 年轻代:复制算法
    • 存活对象较少,复制算法每次的对象复制不会有太大负担;
    • 操作频繁,复制算法标记和复制可并发处理,效率较高;
  • 老年代:标记-整理算法
    • 存活对象较多,减少内存碎片,提高可用性
  • 永久代(元空间):不作考虑

6. Who:谁去处理垃圾?——垃圾回收器

垃圾回收器是垃圾回收算法的执行者,常见的垃圾回收器如下图所示:
在这里插入图片描述

连线部分说明这两个垃圾回收器能够搭配使用。

6.1 年轻代-Serial收集器

  • 回收算法:复制算法
  • 单线程:执行回收算法的时候是单线程;适用于并发能力较低的系统。
  • Stop the World:一般线程和回收线程无法并行,执行回收算法需要中断其他线程,这个现象称为Stop the World(乱入Dio的“咋瓦鲁多”)。
    • Stop the World现象会导致系统暂停,引出垃圾收集停顿时间这一参数,影响用户体验,因此需要尽量避免;
  • 优点:简单高效,适用于单核CPU;
  • 缺点:无法并行,且单线程处理效率较低;
  • 启用方式:-XX:+UseSerialGC

6.2 年轻代-ParNew收集器

  • 回收算法:复制算法
  • 多线程:执行回收算法的时候是多线程;
  • 也会存在Stop the World现象,除了多线程的改进之外,和Serial收集器没有太大区别;
  • 优点:多线程处理效率高,适用于多核CPU;
  • 缺点:一般线程和回收线程无法并行处理;
  • 启用方式:-XX:+UseParNewGC

6.3 年轻代-Parallel Scavenge收集器

  • 回收算法:复制算法
  • 关注吞吐量
    吞吐量 = 用户线程运行时间 / (用户线程运行时间 + 垃圾回收线程运行时间)
    
  • 相关参数
      1. 垃圾收集停顿时间
      • 设置方式:-XX:MaxGCPauseMillis=一个数值
      • 停顿时间过大将会直接影响每次垃圾回收的用户体验,停顿时间过小则会导致垃圾回收频繁;
      1. 吞吐量大小
      • 设置方式:-XX:GCTimeRatio=一个数值
      • 默认取值为99%,表示只有1%的时间用于垃圾回收;
      1. 自适应模式
      • 设置方式:-XX:+UseAdaptiveSizePolicy
      • 设置自适应模式之后,内存中的新生代分配比例和老年代的时间参数可自行调整,达到吞吐量、停顿时间和内存占用的平衡;
  • 是JDK1.8的默认垃圾回收器
  • 启用方式:-XX:+UseParallelGC

6.4 老年代-SerialOld收集器

  • 回收算法:标记-整理算法
  • 单线程,可类比年轻代的Serial收集器,优缺点同理
  • CMS收集器的后备算法

6.5 老年代-ParallelOld收集器

  • 回收算法:标记-压缩算法
  • 关注吞吐量,可类比年轻代的Parallel Scavenge收集器
  • 多线程,线程数通过-XX:ParallelGCThreads设置,默认为CPU核心数
  • 启用方式:-XX:+UseParallelOldGC

6.6 老年代-CMS(Concurrent Mark Sweep)收集器

  • 回收算法:标记-清除算法
  • 关注停顿时间,期望有较短的垃圾回收停顿时间,从而优化用户体验;
  • 回收步骤:
    • 初始标记:适用可达性分析法的思想,标记GC Roots能直接关联到的对象,速度较快;
    • 并发标记:一般线程和回收线程并行,对此时标记状态出现变化的实例进行统计;
    • 重新标记:根据并发标记的结果,对标记状态发生变化的实例进行重新标记,这一步相对较慢;
    • 并发清除:清理垃圾实例,释放内存空间;这一步可以和一般线程并行;
  • 相关参数:
    • 触发阈值:
      • 设置方式:-XX:CMSInitiatingOccupancyFraction=一个数值
      • 和之前讨论的何时进行垃圾回收的触发机制不同,CMS在处理老年代的时候,不会等到内存完全占满,而是会设置一个阈值,默认数值为68%,占用内存空间超过这个阈值就进行垃圾回收处理。
    • 整理标记
      • 设置方式:-XX:+UseCMSCompactAtFullCollection
      • 如果设置这一标记,则垃圾回收之后会进行一次整理,合并内存碎片。
  • 优点:并发收集,提高执行效率;减少停顿时间,用户体验佳
  • 缺点:无法处理浮动垃圾,对CPU资源敏感,且标记清除算法会产生内存碎片

6.7 年轻代和老年代-G1(Garbage First)收集器

  • 回收算法:整体来看是标记-整理算法,局部来看是复制算法
  • 关注停顿时间,也关注高吞吐量(我全都要.jpg);
  • 分区:不同于之前所讨论的分代划分内存区域的方式,G1回收器将内存划分为一个又一个单元区域,称为Region
    • 设置方式:-XX:G1HeapRegionSize=一个数值
    • 每个分区内部可以存放年轻代或者老年代的数据,根据不同的存放数据,将分区划分为四类:
      • E-Eden区:存放年轻代当中Eden区域的数据;
      • S-Survivor区:存放年轻代当中Survivor区域(survivor0和survivor1)的数据;
      • O-Old:存放老年代的一般数据;
      • H-Humongous:存放老年代当中大对象的数据;当占据整个Region一半以上的时候,就会被划分为Humongous区域;
  • 停顿预测模型:用户可以自行设置垃圾回收停顿时间,而G1回收器会根据历史数据构建预测模型,考虑为了满足用户设置的停顿时间,本次垃圾回收可以处理哪几个Region。
  • Region优先级队列:G1浏览器维护一个Region队列,高价值的Region有更高的优先级,在垃圾回收的时候优先处理,这也是Garbage First名字的由来。
  • 回收步骤(和CMS回收器类似):
    • 初始标记
    • 并发标记
    • 重新标记
    • 并发清除
  • 优点:并发操作,并行收集,提高执行效率;关注停顿时间,可预测停顿时间,优化用户体验;可处理浮动垃圾,不会产生内存碎片;

6.8 垃圾回收器对比图

对上述垃圾回收器的对比如下所示:
在这里插入图片描述

面试模拟

Q:介绍一下JVM和垃圾回收机制。
A:从"where"、“which”、“when”、“why”、“how”、"who"的角度,重点介绍触发机制/判断算法/垃圾回收算法/垃圾回收机制

参考资料

  1. JVM之垃圾回收机制(GC)
  2. JVM的垃圾回收机制 总结(垃圾收集、回收算法、垃圾回收器)
  3. 深入理解 JVM 垃圾回收机制及其实现原理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/771454.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【汉诺塔问题分析】

一、背景 汉诺塔问题是一种经典的递归问题,它由法国数学家Huygens在1665年发现,也是一道有趣的数学难题。这道问题的主要目的是将三根柱子上的一堆盘子移动到另一根柱子上,移动过程中每次只能移动一个盘子,并且大盘子不能放在小盘…

【LeetCode热题100】打卡第40天:翻转二叉树回文链表

文章目录 【LeetCode热题100】打卡第40天:翻转二叉树&回文链表⛅前言 翻转二叉树🔒题目🔑题解 回文链表🔒题目🔑题解 【LeetCode热题100】打卡第40天:翻转二叉树&回文链表 ⛅前言 大家好&#xff…

高数-第一章-函数-极限 连续

目录 第一章 函数 极限 连续第一节 函数第二节 极限一、极限的概念与性质(1)数列的极限例1例2 (2)函数的极限(3)极限的性质(保号性重点 有界性)例12例13例14 (4&#xff…

Python 3 拷贝、浅拷贝、直接引用

诸神缄默不语-个人CSDN博文目录 复杂的以后再补。 总的来说,像常数、字符串这种比较简单的变量无所谓,但是对于一些复杂对象(比如list等),如果直接使ba,相当于直接把a的路径给了b,b这个对象的…

stb_image简单使用

简介stb_image stb_image 是一个非常轻量级的、单文件的图像加载库,用于加载和解码多种图像格式(如BMP、JPEG、PNG、GIF等)的图像数据。它由Sean T. Barrett开发,并以公共领域(Public Domain)许可发布&…

【软件测试】web测试bug定位思路总结,“我“不再背锅...

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 需要掌握的知识 …

LabVIEW - 采集声音并保存 wav 文件

1. 题目 编写程序,实现用户点击按钮时,采集声音,显示声音波形,对于采集的声音进行低频段、中频段、高频段分别进行适当的比例放大或者衰减,然后重新合成(三段相加即可),并将合成的声音下入wav格式的文件保存…

【ROS】ROS1人机界面开发:第一个最简ROS+QtGui程序(按钮启动发布者)

【ROS】郭老二博文之:ROS目录 1、创建工程 1)新建工程:Other Project --> ROS Workspace 2)设置工程名称、路径 3)可以通过点击“Browse”来创建目录 注意:使用自带ros插件的qtcreator-ros,无法创建目录、也不能选择目录,这是个bug,因此需要在终端手动创建目录…

江南大学轴承数据故障诊断(利用连续小波变换转换为二维图像,再利用CNN进行故障诊断)

1.江南大学轴承数据集介绍 采样频率:50khz,采样时间:10s 转速:600 800 1000/rpm 内圈:ib 外圈:ob 滚动体:tb 正常:N 以600转速下的内圈故障数据为例展示: 开始数据…

【云原生】Prometheus 之PromQL

前言 当 Prometheus 通过 Exporter 采集到相应的监控指标样本数据后,我们就可以通过PromQL 对监控样本数据进行查询,从而对相应的数据样本进行分析以及制定报警规则。 1. PromQL的简介 PromQL(Prometheus Query Language)是 Prome…

SaleSmartly,客户满意度调查的绝对好助手

企业使用客户满意度调查来收集反馈并评估客户满意度水平,包括有关产品质量、服务、支持和整体满意度的问题。客户满意度调查的主要目标是直接从客户那里收集有价值的见解,以了解他们的需求、偏好和期望。这种反馈可以帮助企业确定需要改进的领域&#xf…

STM32案例学习 GY-39环境监测传感器模块

STM32案例学习 GY-39环境监测传感器模块 硬件平台 野火STM32F1系列开发板正点STM32F1系列开发板STM32F103ZET6核心板GY-39环境监测传感器模块 GY-39环境监测传感器模块 GY-39 是一款低成本,气压,温湿度,光强度传感器模块。工作电压 3-5v…

JS-27 前端数据请求方式;HTTP协议的解析;JavaScript XHR、Fetch的数据请求与响应函数;前端文件上传XHR、Fetch

目录 1_前端数据请求方式1.1_前后端分离的优势1.2_网页的渲染过程 – 服务器端渲染1.3_网页的渲染过程 – 前后端分离 2_HTTP协议的解析2.1_HTTP概念2.2_网页中资源的获取2.3_HTTP的组成2.4_HTTP的版本2.5_HTTP的请求方式2.6_HTTP Request Header2.7_HTTP Response响应状态码 3…

京东自动化功能之商品信息监控是否有库存

这里有两个参数,分别是area和skuids area是地区编码,我这里统计了全国各个区县的area编码,用户可以根据实际地址进行构造skuids是商品的信息ID填写好这两个商品之后,会显示两种状态,判断有货或者无货状态,详情如下图所示 简单编写下python代码,比如我们的地址是北京市…

Kaggle:树叶分类(使用Jupyter)

竞赛网址:https://www.kaggle.com/c/classify-leaves # 首先导入包 import torch import torch.nn as nn import pandas as pd import numpy as np from torch.utils.data import Dataset, DataLoader from torchvision import transforms from PIL import Image i…

uniapp 小程序 实时拍照(仅拍照)限制上传5张 可预览 可删除

效果图: common.js /*** 预览图片*/ const previewImage (current,list)>{// 预览图片uni.previewImage({current: current,urls: list}); } /*** 删除图片*/ const removeImage (current,list)>{var photoFilesList list;photoFilesList.splice(curren…

AJAX:宏任务与微任务

异步任务划分为了 宏任务:由浏览器环境执行的异步代码 微任务:由 JS 引擎环境执行的异步代码 宏任务和微任务具体划分: 左边表格是宏任务,右边是微任务 事件循环模型 /*** 目标:阅读并回答打印的执行顺序 */ console…

国内软件外包公司开发流程

当企业发展到一定阶段后,现有市场上通用型的软件往往无法满足自身的业务需求,这就需要企业定制化开发软件系统来满足自身独特的需求。而传统企业往往没有自己的软件研发队伍,在开发软件系统时快速新建团队风险比较高,可以采用外包…

Docker 网络模型:多角度分析容器网络的原理与应用

🌷🍁 博主 libin9iOak带您 Go to New World.✨🍁 🦄 个人主页——libin9iOak的博客🎐 🐳 《面试题大全》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~&#x1f33…

FPGA adrv9002 4收4发板卡,支持NVME SATA EMMC 光口 FMC

板卡采用ADI 射频直采芯片ADRV9002 ,支持4收4发支持外部本振 跳频 同时支持4X 10G光口对外传输,FMC扩展 。同时支持4X NVME接口,可以实时流盘,备份一路SAT A接口,板卡同时预留了EMMC,可以PS PL选通访问&…