JVM篇--垃圾回收高频面试题

JVM垃圾回收

1 简单说下Java垃圾回收机制?

首先在java运行过程中,其实程序员并不需要去显示的调用程序来释放对象的内存,而是由虚拟机来完成的,具体来看是在jvm中有个垃圾回收线程,这个线程是个守护线程,这个线程会在虚拟机空闲或者在当前堆内存不足时,才会触发执行,扫面那些没有被任何引用的对象,并将它们添加到要回收的集合中,进行回收。

2 垃圾回收器的基本原理是什么?优点有哪些,垃圾回收器可以马上回收内存吗?

其实jvm的垃圾回收,在我们一开始创建对象的时候,GC就会去监控这个对象的地址,大小和使用情况,而jvm在进行回收的时候主要是采用了可达性分析算法,通过这种方式确定哪些对象是"可达
的",哪些对象是"不可达的"。当GC确定一些对象为"不可达"时,GC就有责任回收这些内存空间。
其实垃圾回收的优点也很明显,首先就是不用像其他语言一样需要程序员手动的去释放内存,其次垃圾回收机制可以有效的防止内存泄露,并且可以做到对内存进行更有效的利用
对于垃圾回收的时机,虽然程序员可以通过执行System.gc(),通知GC运行,但是Java语言规范并不保证GC一定会执行。

3 怎么判断对象是否可以被回收?

我们刚才说到jvm会自动的对内存进行回收,因此它在回收的时候就需要知道 哪些对象是存活的,不需要被回收;而哪些对象又是垃圾对象,可以被回收,那么它具体是怎么判断的呢?
其实有两种判断方式
1 引用计数法:说白了也就是会为每一个对象创建一个引用计数,有对象引用时,计数器会加1,而引用释放时计数器会减1,而当计数器为0时也就表示对象可以被回收,它有一个缺点就是不能解决循环引用的问题
2 可达性分析算法:也就是会从GC root开始向下搜索,搜索所走过的路径称为引用链。当一个对象到 GC Roots 没有任何引用链相连时,则证明此对象是可以被回收的。

4 JVM 运行时 堆内存如何分代?

Java 堆从 GC 的角度还可以细分为: 新生代和老年代。
而新生代 又可以分为 (Eden 区、 From Survivor 区和 To Survivor 区)
一般新生代和老年代的比例约为 1:2
同时 eden区:s1区:s2区约为 8:1:1
在这里插入图片描述
同时对于新生代来说 JVM 每次只会使用 Eden 和其中的一块 Survivor 区域来为对象服务,所以无论什么时候,总是有一块 Survivor区域是空闲着的。
整体的流程就是 :新建的对象会首先分配在Eden区中,经历一次Minor GC,Eden中的存活对象就会被移动到第一块survivor S0区,Eden被清空;等Eden区再满了,就再触发一次Minor GC,Eden和S0中的存活对象又会被复制送入第二块survivor S1 区,就是通过这样不断地复制–>清空—>互换来实现年轻代的垃圾回收即minor gc
同时年轻代采用复制算法,也解决了内存碎片化的问题

我们接着再看老年代
老年代的对象特点 一般都是长生命周期的对象,也就是比较稳定,因此 MajorGC (常常称之为 FULL GC)不会频繁执行。
同时注意在进行 FULL GC前一般都先进行了一次 MinorGC,使得有新生代的对象晋身入老年代,导致空间不够用时才触发。当无法
找到足够大的连续空间分配给新创建的较大对象时也会提前触发一次 MajorGC 进行垃圾回收腾出空间。

FULL GC 采用标记清除算法,同时会产生内存碎片

永久代 (或者 jdk1.8元空间)
指内存的永久保存区域,主要存放 Class 和 Meta(元数据)的信息,Class 在被加载的时候被放入永久区域, 它和和存放实例的区域不同,GC 不会在主程序运行期对永久区域进行清理。所以这也导致了永久
代的区域会随着加载的 Class 的增多而胀满,最终抛出 OOM 异常。

5 JVM内存为什么要分成新生代,老年代,永久代(即为什么要分代)?新生代中为什么要分为Eden和Survivor?

这个问题 其实想一下就能理解 分代主要还是 为了提高对象内存分配和垃圾回收的效率。
试想一下,如果堆内存没有区域划分,所有的新创建的对象和生命周期很长的对象放在一起,随着程序的执行,堆内存需要频繁进行垃圾收集,而每次回收都要遍历所有的对象,遍历这些对象所花费的时间代价是巨大的,会严重影响我们的 GC 效率

而有了内存分代,情况就不同了,新创建的对象会在新生代中分配内存,经过多次回收仍然存活下来的对象存放在老年代中,
静态属性、类信息等存放在永久代(或者元空间)中,
新生代中的对象存活时间短,只需要在新生代区域中频繁进行 GC,老年代中对象生命周期长,内存回收的频率相对较低,不需要频繁进行回收。

而新生代为什么要分为eden区和survivor区 ?

  1. 我们试想下 如果没有Survivor,Eden区每进行一次Minor GC,存活的对象就会被送到老年代。这样一来老年代很快被填满,触发Major GC.
    又因为老年代的内存空间远大于新生代,进行一次Full GC消耗的时间比Minor GC长得多,
    所以总结来看 分为eden区 和s区可以减少对象频繁地被输送到老年代,进而减少了full gc的发生。
  2. 同时分为两个eden区,利用这种复制算法也避免了内存的碎片化。

6 JVM中一次完整的GC流程是怎样的,对象如何晋升到老年代?

针对这个问题,思路就是可以先描述下java堆内存的划分,以及minor gc,major gc,full gc 以及他们之间的转换过程。
首先我们知道java堆可以分为 老年代 + 新生代;同时 新生代 = Eden + S0 + S1
整体的过程就是:

  1. 当 Eden 区的空间满了, Java虚拟机会触发一次 Minor GC,以收集新生代的垃圾,存活下来的对象,则会转移到 Survivor区
  2. 而 如果对象在Eden出生,并经过第一次Minor GC后仍然存活,并且被Survivor容纳的话,年龄设为1,每熬过一次Minor GC,年龄+1,若年龄超过一定限制(15)----即经过静态年龄判断规则后,则被晋升到老年态。即长期存活的对象进入老年态。
    当然对于大对象 (比如那种连续内存空间的java对象,比如那种很长的字符串)也会直接进入老年代
  3. 当老年代满了无法容纳更多的对象,就会发生major gc清理掉老年代,同时major gc会伴随着至少一次minor gc。
  4. 而Full GC 会清理整个内存堆 – 包括年轻代和年老代。

那么Minor GC与Full GC分别在什么时候发生?
新生代内存不够用时候发生minor gc也叫YGC;JVM内存不够的时候发生FGC

7 JVM 有哪些垃圾回收算法?

可以分为 四种,即标记-清除算法;复制算法;标记整理算法; 分代收集算法;
我们首先看标记清除算法
该算法分为“标记”和“清除”阶段:首先标记出所有不需要回收的对象,在标记完成后统一回收掉所有没有被标记的对象。
适用场合:存活对象较多的情况、适用于年老代。
优点:比较简单,不需要对象的移动
缺点:会产生大量的内存碎片;效率也比较低

复制算法
因为标记清除算法会产生内存碎片 因此在他的基础之上引入复制算法
说白了复制算法 就是 把内存空间划为两个相等的区域,每次只使用其中一个区域。
垃圾收集时,遍历当前使用的区域,把存活对象复制到另外一个区域中,最后将当前使用的区域的可回收的对象进行回收。
优点:按顺序分配内存即可,实现简单、运行高效,不用考虑内存碎片
缺点:可用的内存大小缩小为原来的一半,对象存活率高时会频繁进行复制。
在这里插入图片描述

标记整理算法
刚才说了复制算法 解决了内存碎片化的问题,但是它也有一个问题,就是内存的使用率并不高,需要频繁地进行来回复制,
因此又引入了标记整理算法,说白了 就是在标记可回收的对象后将所有存活的对象压缩到内存的一端,使他们紧凑的排列在一起,然后对端边界以外的内存进行回收。回收后,已用和未用的内存都各自一边。
优点是:解决了内存碎片化的问题,相比于复制算法 内存使用率也提高了
缺点:仍需要进行局部对象移动,一定程度上降低了效率
在这里插入图片描述
分代收集算法:
分代收集法是目前大部分 JVM 所采用的方法,顾名思义是根据对象的存活周期将内存划分为几块。一般包括年轻代、老年代 和 永久代,并根据各年代特点分别采用最适当的 GC 算法
老生代的特点是每次垃圾回收时只有少量对象需要被回收,
新生代的特点是每次垃圾回收时都有大量垃圾需要被回收,
因此可以根据不同区域选择不同的算法
在这里插入图片描述
新生代与复制算法
每次垃圾收集都能发现大批对象已死, 只有少量存活. 因此选用复制算法, 只需要付出少量存活对象的复制成本就可以完成收集,当然并不是按照1:1来划分新生代,一般是按照eden区,s1区,s2区 =8:1:1 来划分
老年代与标记整理算法
因为老年代对象存活率高、没有额外空间对它进行分配担保, 就必须采用“标记—清理”或“标记—整理” 算法来进行回收, 不必进行内存复制, 且直接腾出空闲内存。因而采用 标记整理算法。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

揭秘AI换脸技术:从原理到应用

随着人工智能技术的不断发展,AI换脸技术逐渐成为人们关注的焦点。这项神奇的技术能够将一张图像或视频中的人脸替换成另一张人脸,让人不禁惊叹科技的神奇。那么,AI换脸技术究竟是如何实现的呢?本文将带您深入了解AI换脸技术的原理…

【JavaEE】网络原理:网络中的一些基本概念

目录 1. 网络通信基础 1.1 IP地址 1.2 端口号 1.3 认识协议 1.4 五元组 1.5 协议分层 什么是协议分层 分层的作用 OSI七层模型 TCP/IP五层(或四层)模型 网络设备所在分层 网络分层对应 封装和分用 1. 网络通信基础 1.1 IP地址 概念:IP地址…

Qt 状态机框架:The State Machine Framework (二)

传送门: Qt 状态机框架:The State Machine Framework (一) Qt 状态机框架:The State Machine Framework (二) 1、利用并行态避免态的组合爆炸 假设您想在单个状态机中对汽车的一组互斥属性进行建模。假设我们感兴趣的属性是干净与肮脏,以及移动与不移动。需要四个相互排斥的…

手把手教你如何快速定位bug,如何编写测试用例,快来观摩......

手把手教你如何快速定位bug,如何编写测试用例,快来观摩......手把手教你如何快速定位bug,如何编写测试用例,快来观摩......作为一名测试人员如果连常见的系统问题都不知道如何分析,频繁将前端人员问题指派给后端人员,后端人员问题指派给前端人员&#xf…

cetos7搭建部署k8s 版本1.28

主机分配 内存最少是4G cpu个数最少两个 IP内存CPU主机名192.168.231.12044K1 192.168.231.12144K2192.168.231.12244K3 关闭防火墙 systemctl stop firewalled 关闭swap vim /etc/fstab 设置主机名称 hostnameset 安装docker 三个主机 初始化集群 在mas…

【unity学习笔记】语音驱动blendershape

1.导入插件 https://assetstore.unity.com/packages/tools/animation/salsa-lipsync-suite-148442 1.选择小人,点击添加组件 分别加入组件: SALSA EmoteR Eyes Queue Processor(必须加此脚本):控制前三个组件的脚本。…

ASP.NET Core SingleR:初次体验和简单项目搭建

文章目录 前言应用场景SignalR 网站长什么样?第一个ASP.NET core SignalR程序确定SignalR版本新建MVC项目添加unpkg管理器添加客户端添加ChatHub文件添加SignalR服务添加网页运行测试浏览器Websocket调试type1type6Type为其它时 总结 前言 平常的网页通讯都是基于H…

Python武器库开发-武器库篇之Fofa-API使用(四十六)

Python武器库开发-武器库篇之Fofa-API使用(四十六) FOFA(FOcus Observation of Futures Assets)是一款专业的网络资产搜索引擎,旨在帮助企业发现和评估网络上的潜在安全风险。FOFA的基本原理是通过搜索引擎的方式,按照关键词对互…

【51单片机Keil+Proteus8.9】温室盆栽灌溉系统

实验五 实验名称 温室盆栽灌溉系统 软件设计: 1. 定义对应的引脚和端口的别名。 2. 编写延时函数,用于控制程序的执行速度。 3. 编写LCD控制函数,包括发送命令和发送数据两种操作。 4. 编写显示函数,用于在LCD上显示字符串…

PHP+MySQL组合开发:微信小程序万能建站源码系统 附带完整的搭建教程

随着移动互联网的快速发展,微信小程序已成为企业进行移动营销的重要工具。然而,对于许多中小企业和个人开发者来说,开发一个功能完善、用户体验良好的小程序是一项复杂的任务。罗峰给大家分享一款微信小程序万能建站源码系统。该系统采用PHPM…

小白准备蓝桥杯之旅(c/c++b组)

前言:省赛获奖比例高达百分之60,只要比一半的人努力,你就能大概率获奖。 寒假做的3件事 1.稳基础 熟练掌握基础语法部分,c比c多个stl库优势,c语言的同学需要会实现c中stl库部分 2.刷真题 大概比赛前30天,坚持每天做…

ros2 基础教程-使用ROS 2进行相机标定

ROS 2进行相机标定(Camera Calibration) 相机(摄像头)是一种非常精密的光学仪器,对外界环境的感知非常敏感。由于摄像头内部和外部的一些原因,摄像头采集的图像常常会发生一定的畸变。如果直接将采集到的图…

JAVA和C++ SECS/GEM300开发和概念

编译SECS示例程序 1. 示例程序使用默认路径: D:\SECS 稳定版\SECS Debug\ 2. 该操作分为俩步 ① 将C#的Secs库编译成设备相同Net版本。 如.net3.5、4.0、4.5等等 ② 编译金南瓜SECS demo程序 编译C#的SecsEquip.dll 1. 找到SecsEquip项目 项目文件 使用Visua…

电商平台spu和sku的完整设计

一、关于数据库表的设计 1、商品属性表 比如一个衣服有颜色、尺码、款式这个叫属性表 -- ------------------------ -- 商品属性表 -- ------------------------ DROP TABLE IF EXISTS attribute; CREATE TABLE attribute (id int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT CO…

LabVIEW振动数据采集与分析系统

在这个项目中, LabVIEW软件配合精确的硬件组件,以实现高效的振动数据采集和复杂信号分析。硬件方面,系统采用了PCB振动加速度传感器的高灵敏度传感器,以及NI9234型号的数据采集卡,确保了数据采集的高精度和可靠性。软件…

yarn包管理器在添加、更新、删除模块时,在项目中是如何体现的

技术很久不用,就变得生疏起来。对npm深受其害,决定对yarn再整理一遍。 yarn包管理器 介绍安装yarn帮助信息最常用命令 介绍 yarn官网:https://yarn.bootcss.com,学任何技术的最新知识,都可以通过其对应的网站了解。无…

(C语言)编译和链接

前言͟͟͞͞💌:对于现在的各种编译器而言许多都是好多个功能的集成,那么我们的代码到底是如何去实现的呢?难道我们的计算机可以直接读懂我们所写的代码,并运行吗?对于很多细心的小伙伴们可能会想这样的问题…

基于docker创建nginx容器

docker一键安装可以参考我这个博客:一键安装docker 1.创建基础容器 docker run -p280:280 --name nginx -d nginx创建挂载到容器的宿主机文件夹 mkdir -p /home/000nginx-ebrms-ftp/html mkdir -p /home/000nginx-ebrms-ftp/logs mkdir -p /home/000nginx-ebrms-f…

Win10 打开文件突然鼠标变成一个蓝色大圈卡住点不了也打不开文件,重启电脑也是这样

环境: Win10 专业版 加密客户端环境 问题描述: Win10 打开桌面word文件突然鼠标变成一个蓝色大圈卡住点不了也打不开文件,重启电脑也是这样,只有蓝色圈变大没有鼠标指针出现圈卡着不会动,和那些有鼠标箭头加小蓝色圈不一样 解决方案: 某网上查看的,还是要自己排查…

Java 内存模型深度解析

优质博文:IT-BLOG-CN 一、并发编程模型的两个关键问题 【1】并发中常见的两个问题:线程之间如何通信及线程之间如何同步。通信是指线程之间以何种机制来交换信息。在命令式编程中,线程之间的通信机制有两种:内存共享和消息传递&…