JVM--垃圾回收

垃圾回收的概念 

垃圾回收主要针对的是堆中的对象,堆是一个共享的区域,创建的对象和数组都放在这个位置。但是我们不能一直的创建对象,也不是所有的对象能一直存放,如果不进行垃圾回收,内存迟早会耗尽,及时的垃圾回收能提高内存的利用率以及存储效率。

什么样的对象进行垃圾回收?

如果一个或多个对象没有任何的引用指向它了,那么这个对象现在就是垃圾,如果定位了垃圾,则有可能会被垃圾回收器回收。

如何定位垃圾?

引用计数法:一个对象被引用了一次,在当前对象头上递增一次引用次数,如果这个对象的引用次数为0,代表这个对象可以回收。

在创建对象时,对象对应的引用次数为1,如果后续给对象赋值NULL,则对象的引用次数会变为0,此时表明当前的对象是可以被垃圾回收的。

当对象间出现了循环引用时,引用计数法就会失效。会导致内存泄露

创建a和b之后,并且创建的对象之间有循环引用,则两个对象的堆内存的ref初始值为2,在设置对象a和b为null后,由于循环引用的存在,内存区域的ref为1,导致这两块内存区域一直不能回收

可达性分析算法

现在的虚拟机采用的都是通过可达性分析算法来确定哪些内容是垃圾。

  • Java虚拟机中的垃圾回收器采用可达性分析来探索所有存活的对象
  • 可达性算法的流程:扫描堆中的对象,看是否能够沿着GCRoot对象为起点的引用链找到该对象,找不到,表示可以回收

如上图所示,由于从GC Roots开始沿着引用链进行寻找,并不能找到X 和 Y,因此X和Y可以回收

哪些对象可以作为GC Root呢?

1.虚拟机栈(栈帧中的本地变量表)中引用的对象

2.方法区中类静态属性引用的对象

3.方法区中常量引用的对象

4.本地方法栈中JNI(即一般说的Native方法)引用的对象

垃圾回收算法

JVM垃圾回收算法有哪些?

标记清除算法

将垃圾回收分为2个阶段,分别是标记和清除。

1.根据可达性分析算法得出的垃圾进行标记

2.对这些标记为可回收的内容进行垃圾回收

标记清除算法的优缺点

优点:标记和清除的速度很快

缺点:碎片化较为严重,内存不连贯


复制算法

1.将内存划分为两个区域根据可达性分析算法得出的垃圾进行标记

2.将存活的对象复制到另一块内存区域。然后清理边界以外的垃圾


复制算法的优缺点

优点:在垃圾对象多的情况下,效率较高。清理后,内存无碎片。

缺点:分配的2块内存空间,在同一时刻,只能使用1个,内存的使用率较低

标记整理算法

1.根据可达性分析算法得出的垃圾进行标记

2.对这些标记为可回收的内容进行垃圾回收

3.清除之后,将存活的对象进行整理,向一端移动,然后清理边界意外的垃圾

优缺点同标记清除算法,解决了标记清除算法的碎片化的问题,同时,标记压缩算法多了一步,对象移动内存位置的步骤,其效率也有有一定的影响。

JVM的分代回收

堆的区域划分

在java8时,堆被分为了两份:新生代和老年代【1:2]

对于新生代,内部又被分为了三个区域。

  • 伊甸园区Eden,新生的对象都分配到这里
  • 幸存者区survivor(分成from和to)

Eden区,from区,to区[8:1:1]

对象回收分代回收策略
  • 新创建的对象,都会先分配到eden区
  • 当伊甸园内存不足,标记伊甸园与from(现阶段没有)的存活对象
  • 将存活对象采用复制算法复制到to中,复制完毕后,伊甸园和from内存都得到释放
  • 经过一段时间后伊甸园的内存又出现不足,标记eden区域to区存活的对象,将存活的对象复制from区
  • 当幸存区对象熬过几次回收(最多15次),晋升到老年代(幸存区内存不足或大对象会导致提前晋升)
MinorGC、Mixed GC、FulIGC的区别是什么?

MinorGC【youngGC】:发生在新生代的垃圾回收,暂停时间短(STW)

MixedGC:新生代+老年代部分区域的垃圾回收,G1收集器特有

FulIGC:新生代+老年代完整垃圾回收,暂停时间长(STW),应尽力避免

STW(Stop-The-World):暂停所有应用程序线程,等待垃圾回收的完战

JVM中的垃圾回收器

在jvm中,实现了多种垃圾收集器,包括:

  • 串行垃圾收集器:Serial GC、Serial Old GC
  • 并行垃圾收集器:Parallel Old GC、ParNew GC
  • CMS(并发)垃圾收集器:CMSGC,作用在老年代
  • G1垃圾收集器,作用在新生代和老年代

串行垃圾回收器

  • Serial和SerialOld串行垃圾收集器,是指使用单线程进行垃圾回收,堆内存较小,适合个人电脑
  • Serial 作用于新生代,采用复制算法
  • SerialOld 作用于老年代,采用标记-整理算法
  • 垃圾回收时,只有一个线程在工作,并且java应用中的所有线程都要暂停(STW),等待垃圾回收的完成。

并行垃圾收集器

  • ParallelNew和ParallelOld是一个并行垃圾回收器,JDK8默认使用此垃圾回收器
  • ParallelNew 作用于新生代,采用复制算法
  • ParallelOld 作用于老年代,采用标记-整理算法
  • 垃圾回收时,多个线程在工作,并且java应用中的所有线程都要暂停(STW),等待垃圾回收的完成。

CMS(并发)垃圾收集器


CMS全称ConcurrentMarkSweep,是一款并发的、使用标记-清除算法的垃圾回收器,该回收器是

针对老年代垃圾回收的,是一款以获取最短回收停顿时间为目标的收集器,停顿时间短,用户体验

就好。其最大特点是在进行垃圾回收时,应用仍然能正常运行。

为什么要进行重新标记?

可能出现一种情况,当X一开始没有在引用链上,但是在并发标记期间,某个对象对X引用,此时就不能对X进行回收,因此需要重新标记。

G1垃圾回收器

  • 应用于新生代和老年代,在JDK9之后默认使用G1
  • 划分成多个区域,每个区域都可以充当eden,survivor,old,humongous,其中humongous专为大对象准备
  • 采用复制算法
  • 响应时间与吞吐量兼顾
  • 分成三个阶段:新生代回收(stw)、并发标记(重新标记stw)、混合收集
  • 如果并发失败(即回收速度赶不上创建新对象速度),会触发FullGC
垃圾回收的流程

YoungCollection(年轻代垃圾回收)

1.初始时,所有区域都处于空闲状态

2.创建了一些对象,挑出一些空闲区域作为伊甸园区存储这些对象

3.当伊甸园需要垃圾回收时,挑出一个空闲区域作为幸存区,用复制算法复制存活对象,需要暂停用户线程

在标记的过程中或者是在复制的过程中,都需要触发STW

4.随着时间流逝,伊甸园的内存又有不足,将伊甸园以及之前幸存区中的存活对象,采用复制算法,复制到新的幸存区,其中较老对象晋升至老年代

YoungCollection+ConcurrentMark(年轻代垃圾回收+并发标记)
5.当老年代占用内存超过阈值(默认是45%)后,触发并发标记,在老年代中找到存活的对象,这时无需暂停用户线程

6.并发标记之后,会有重新标记阶段解决漏标问题,此时需要暂停用户线程。

MixedCollection(混合垃圾回收)
混合收集阶段中,参与复制的有eden、survivor、old。此时不会对所有老年代区域进行回收,而是根据暂停时间目标优先回收价值高(存活对象少)的区域(这也是GabageFirst 名称的由来)。复制完成,内存得到释放。进入下一轮的新生代回收、并发标记、混合收集。

混合收集可能会持续多次。

新生代中存活的对象会被复制到最新的幸存区,之前的幸存区以及老年代中存活的对象,将会放在一个老年代中。

强引用、软引用,弱引用,虚引用的区别

强引用:只有所有GCRoots对象都不通过【强引用】引用该对象,该对象才能被垃圾回收。只要所有GC Roots能找到,就不会被回收

软引用:需要配合SoftReference使用,当垃圾多次回收,内存依然不够的时候会回收软引用对象

弱引用:需要配合WeakReference使用,只要进行了垃圾回收,就会把弱引用对象回收

虚引用:必须配合引用队列使用,被引用对象回收时,会将虚引用入队,由ReferenceHandler线程调用虚引l用相关方法释放直接内存(虚引用的外部资源)

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

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

相关文章

【教程】继承中的访问控制 C++

目录 简介public,protected 和 private继承中的 public,protected 和 private示例 简介 在 C 中派生类可以通过 public,protected 和 private 三种修饰符决定基类成员在派生类中的访问级别 public,protected 和 private 公有成…

【2025】基于python+django的驾校招生培训管理系统(源码、万字文档、图文修改、调试答疑)

课题功能结构图如下: 驾校招生培训管理系统设计 一、课题背景 随着机动车保有量的不断增加,人们对驾驶技能的需求也日益增长。驾校作为驾驶培训的主要机构,面临着激烈的市场竞争和学员需求多样化等挑战。传统的驾校管理模式往往依赖于人工操作…

要登录的设备ip未知时的处理方法

目录 1 应用场景... 1 2 解决方法:... 1 2.1 wireshark设置... 1 2.2 获取网口mac地址,wireshark抓包前预过滤掉自身mac地址的影响。... 2 2.3 pc网口和设备对接... 3 2.3.1 情况1:... 3 2.3.2 情…

一.ffmpeg打开麦克风,录制音频并重采样

一.windows windows下使用msys编译ffmpeg,先编译libx264和libx265,然后编译ffmpeg的时候需要添加这两个库的路径才能--enable;为什么ffplay--enable了还是没有呢,仔细看编译打印,可能刚有一段报错提示SDL找不到&#…

go 安装swagger

1、依赖安装: # 安装 swag 命令行工具 go install github.com/swaggo/swag/cmd/swaglatest# 安装 gin-swagger 和 swagger 文件的依赖 go get -u github.com/swaggo/gin-swagger go get -u github.com/swaggo/files 2、测试 cmd中输入: swag -v 如果…

网络安全反渗透 网络安全攻防渗透

网络渗透防范主要从两个方面来进行防范,一方面是从思想意识上进行防范,另一方面就是从技术方面来进行防范。 1.从思想意识上防范渗透 网络攻击与网络安全防御是正反两个方面,纵观容易出现网络安全事故或者事件的公司和个人,在这些…

java泛型通配符?及上下界(extends,super)保证安全性、灵活性、可读性

在 Java 中,泛型通配符(?)用于表示未知类型,通常用于增强泛型的灵活性。通配符可以与上下限结合使用,以限制泛型的范围。以下是通配符及上下限的使用示例: 1. 无界通配符 (?) 无界通配符表示可以接受任意…

技术视界|构建理想仿真平台,加速机器人智能化落地

在近期的 OpenLoong 线下技术分享会 上,松应科技联合创始人张小波进行了精彩的演讲,深入探讨了仿真技术在机器人智能化发展中的关键作用。他结合行业趋势,剖析了现有仿真平台的挑战,并描绘了未来理想仿真系统的设计理念与实现路径…

uniapp-x 之useAttrs只读

数据类型: useAttrs在web端拿到的是obj,app拿到的是map 是否可以修改内部元素: 否,只读 这意味着你想这样写代码将会无效 let attrsuseAttrs();console.log("attrs",attrs, attrs instanceof Map)//appif(attrs ins…

Python 正则表达式模块 re

Python 正则表达式模块 re flyfish 一、正则表达式基础 1. 什么是正则表达式? 正则表达式(Regular Expression, RE)是一种用于匹配、查找和替换文本模式的工具,由普通字符(如字母、数字)和特殊字符&…

【商城实战(33)】解锁版本迭代与更新策略

【商城实战】专栏重磅来袭!这是一份专为开发者与电商从业者打造的超详细指南。从项目基础搭建,运用 uniapp、Element Plus、SpringBoot 搭建商城框架,到用户、商品、订单等核心模块开发,再到性能优化、安全加固、多端适配&#xf…

环境配置 | 5分钟极简Git入门:从零上手版本控制

你是否刚接触Git?别担心!这篇指南将用最简单的步骤带你掌握Git核心操作,快速开启版本控制之旅!✨ 1.git在win10上的下载安装 1.1.下载git 打开官方网站 Git - Downloadshttps://git-scm.com/downloads ​ ​​ 1.2.git安装 …

计算机网络——DNS

一、什么是DNS? DNS(Domain Name System,域名系统) 是互联网的核心服务,负责将人类可读的域名(如 www.baidu.com)转换为机器可识别的 IP地址(如 14.119.104.254)。它像一…

SQLark 实战 | 如何从Excel、csv、txt等外部文件进行数据导入

数据导入导出是应用开发者在平时开发中最常用的操作之一,SQLark 里提供了方便的图形化界面来完成导入导出。本文先和大家分享如何从 Excel、csv、txt 等外部文件导入数据到数据库表中。 👉 前往 SQLark 官网:www.sqlark.com 下载全功能免费版…

docker无法正常拉取镜像问题的解决

目录 1.前言 2.解决方案 1.前言 安装docker后拉取镜像,遇见了如下问题: Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded whil…

k8s系统学习路径

学习 Kubernetes(K8s)需要循序渐进,结合理论知识和实践操作。以下是学习 Kubernetes 的推荐步骤: 1. 先决条件 • 掌握容器基础:先学习 Docker,理解容器化概念(镜像、容器、仓库)、…

@RequestParam、@RequestBody、@PathVariable

1. RequestParam RequestParam:get请求时如果用不到它的3个属性,可以省略;其他请求如果是通过param传送数据,必须使用该注释 要点: 可用于任何类型的请求(get请求数据在请求行中, post请求数据…

麒麟系统利用pycharm生成deb文件

在麒麟系统(Kylin OS)上使用 PyCharm 进行 Python 开发并生成 .deb 可安装软件包,可以按照以下步骤进行操作: 1. 准备工作 安装 PyCharm:确保已经在麒麟系统上安装了 PyCharm,可以使用官方提供的安装包进…

微信小程序接入DeepSeek模型(火山方舟),并在视图中流式输出

引言: DeepSeek,作为一款先进的自然语言处理模型,以其强大的文本理解和生成能力著称。它能够处理复杂的文本信息,进行深度推理,并快速给出准确的回应。DeepSeek模型支持流式处理,这意味着它可以边计算边输…

钉钉(excel)能让表格中不是‘北京’的字符串自动加亮显示(方便查看)以及隔行填充严颜色是斑马色(方便查看)嘛

在钉钉在线表格中,虽然功能相对Excel有所简化,但仍然可以通过条件格式实现对特定内容的高亮显示。以下是具体步骤: 一、在钉钉在线表格中设置条件格式 1. 打开钉钉在线表格 登录钉钉,进入“钉钉在线表格”应用。 打开你需要操作…