根可达算法的根_我的JVM(六):GC的基础概念以及GC算法

d08dd547a424f48fc51b8ffb620b276d.png

一、概述

垃圾收集Garbage Collection通常被称为GC,但是GC一般也指Garbage Collecting(垃圾回收这个动作)或Garbage Collector(垃圾回收器),这些都是是JVM知识体系中非常重要的知识,也是程序员必须要掌握的技能,本文将详细讲述Java垃圾回收的概念机制以及核心算法。

二、分析

1. 什么是垃圾

我们所说的垃圾是指没有任何引用的一个对象或者多个对象(这多个对象相互引用,但是没有一个与主对象挂钩,也就是根可达算法(下文会讲)无法找到这其中任何一个对象)。

我们再来来熟悉两个概念:

(1) 内存泄露:内存泄露是指有的内存地址太过碎片化而无法被利用,我们都知道一个对象创建的时候开辟的内存空间是连续的,所以太过碎片化的内存空间就没办法利用。内存泄露多了也会导致内存溢出。

(2) 内存溢出:内存溢出是指内存已经装满了,无法再装下更多的对象了。

C和C++都是需要开发者用代码手动回收内存的:C语言用free关键字来回收内存,C++用的是delete。但是手动回收内存容易出现两种类型问题:忘记回收(容易引发OOM内存泄露)和多次回收。

后来诞生的java、python等都是自带了垃圾回收器的语音,开发者只管创建对象,对象的销毁不需要手动处理,由专门的垃圾回收器进行回收。

2. 如何定位垃圾

常见的方式有两种:

(1) 引用计数(Reference Count):每当一块内存被一个对象引用,那么计数就+1,当没有对象指向时,计数为0,就表示这块内存可以被回收了,如下图:

c4d523f72f0d3652714a0d1cbc05306c.png

但是引用计数没办法解决垃圾之间互相引用的情况,当几块内存都没有外部引用,但是这几块内存之间相互引用的时候,这几块内存也应该视为垃圾,但是引用计数却不为0,如下图:

04fca9db118c65e73c2001f776cd33a2.png

(2) 根可达算法(Root Searching):当程序运行时,将根对象取出,由根对象出发往下查找,最终找不到的对象,都视为无法由根对象找到,也就是说找不到的对象就都视为垃圾。如下图:

9e350a1aa17c2109ffd76f3736b6e5e5.png

那么哪些对象是根对象呢?主要包含:JVM stack,native method stack,run-time constant pool(运行常量池里的对象),static references in method area(方法区里的静态引用),Clazz等。

3. 常见的垃圾回收算法

主要包含以下3种:

(1) 标记清除(mark sweep):就是将找到的垃圾标记出来,然后直接清除掉。但是这种方式有一个严重的毛病,会使得内存变得碎片化,也就是有多个不连续的内存。

5eae423e5fb6e111182168983ae54640.png

(2) 拷贝算法(copying):这种方式的做法就是将内存平分成两块,在使用的过程中只能在其中一块内存里创建对象,当需要垃圾回收时,将有对象的内存全部复制到另一边,并且将当前区域全部清除。这种方式解决了内存碎片化的问题,但是却浪费了空间,因为每次只能利用一半。

e93bdb5af36f878cdcb2a915570bd4e8.png

(3) 标记压缩(mark compact):这种方式就是在清理垃圾的同时,将同类型的内存空间放置在一起,也就是说在清理的同时进行空间整理,并且多线程时还需要进行线程同步,所以这种方式明显的缺点就是效率偏低。

1ec69b9e104e1f104843df21db6892f5.png

常用的垃圾回收算法就是这3种或者这3种方式的组合。

4. JVM内存分代模型(用于分代垃圾回收算法)

JVM的内存模型是由垃圾回收器决定的,一般分为分代模型和不分代模型,两种内存模型不一样。分代垃圾回收的内存模型如下图:

19b7ce32df860f5253ee8001c7d6258e.png

分代模型在逻辑上分代,在物理层面也就是内存中也是分成了new(新生代)和old(老年代)两个大区域。新生代区又详细分为eden(伊甸园)、survivor1和survivor2。new(年轻代)的对象有两大特点:大量产生;大量回收(大多数情况下,一次回收90%的对象)。所以根据new年轻代的特点,采用的算法是Copying算法;而Old老年代则是采用标记压缩(mark compact)算法,以此保证内存的连续性 。

值得一提的是,new新生代和old老年代的比例默认是1:2。但是这个比例也是JVM调优中可以调节的参数,所以上图写的1:3。eden和survivor1,survivor2的默认比例是8:1:1,也是可以调整的。

为了方便对于分区的理解,我们由一个对象的创建到回收进行分析,分区内变化如下:

496ff2f9102496d76d38bff4a519d025.png

对象分配过程如下:

d71156739e194af4c98074959efc9aa8.png

过程分析:

(1) 当我们new出一个对象,JVM会首先尝试往栈上分配,如果能够分配得下,就分配到栈上分配到栈上的对象有好处就是不需要GC进行管理,什么时候不需要用到此对象了,将对象出栈就可以了。但是分配到栈上的对象是有要求的:第一,对象比较小,因为栈空间本来就不够大;第二,对象比较简答。

(2) 如果栈上分配不下,我们就判断这个对象是不是够大,如果足够大就直接放在老年代区,在老年代区的对象经过一次全量垃圾回收FGC后,才有可能被回收掉。

(3) 如果如果栈上分配不下并且对象不大,就会判断对象能否被存在线程本地分配缓冲区-TLAB(Thread Local Allocation Buffer)。但是不管放不放得下,都是放在新生代区的伊甸区eden。 但是因为堆是共享的,多个线程可以同时创建对象就可能会争夺同一块内存区域,所以为了保证线程安全,Eden区又被分配成一个个线程本地分配缓冲区,这个TLAB是线程私有的,每个线程都有自己的TLAB,避免了多线程环境下使用同步技术带来的性能损耗。

(4) 伊甸区eden的对象在经过一次GC后,如果被回收掉了,那就结束了生命周期。

(5) 伊甸区eden的对象在经过一次GC后,如果没有被回收掉,JVM在整个new新生代区都采用Copying(拷贝算法),将不是垃圾的对象拷贝到幸存者区survivor1,对比上面的堆内存逻辑分区图。幸存者区survivor1中的对象再经过一次GC后如果对象还存活,那么就拷贝到幸存者区survivor2并且清理掉幸存者区survivor1中的所有对象,再有GC就反复这个操作,直到对象的分代年龄达到了移到老年代的界限(一般分代垃圾回收器默认是15,CMS默认是6),就会被移到老年代中,老年代采用标记压缩(mark compact)算法,保证内存的连续性 。

5. 常见的垃圾回收器

jdk从1.0到14.0一共诞生了10种垃圾回收器,如下图:

de4c9c582ebe596de792b2f31790c086.png

分类如下:

(1) 分代模型:Serial,Serial Old,Parallel Scavenge,Parallel Old,ParNew,CMS

(2) 不分代模型:G1(虽然物理模型上没分代,但是逻辑层面上是分代的,jdk1.8及以上的版本建议使用G1,响应时间很快,但是1.8默认是PSPO<Parallel Scavenge和Parallel Old>),ZGC(Oracle官方支持),Shenandoah(小红帽公司开发)

(3) 特殊模型:Epsilon(这种垃圾回收器不回收垃圾,只是跟踪垃圾的产生和回收,但是这个回收只是动作,其实没真正回收。Epsilon有两个用途:<1>用于调试;<2>内存很大,程序很小很快就能运行完成。)

6. 常见垃圾回收器组合参数设定

(1) -XX:+UseSerialGC = Serial New (DefNew) + Serial Old

小型程序默认情况下不会是这种选项,HotSpot会根据计算及配置和JDK版本自动选中收集器。

(2) -XX:+UseParallelGC = Parallel Scavenge + Parallel Old (jdk1.8默认)【PS+Serial Old】

(3) -XX:+UseParallelOldGC = Parallel Scavenge + Parallel Old

我们可以用命令行-XX:+PrintCommandLineFlags查看我们所使用的是哪种垃圾回收器,如下图:

35366905be4f589972de7b9a1248e43e.png

三、总结

通过本文,我们了解了GC的基础概念、常用的垃圾回收算法、以及JVM内存分代模型和所有的垃圾回收器的特点,下一文我们将着重讲解不同垃圾回收器所采用的底层算法及原理,请期待《我的JVM(二):十种垃圾回收器所采用的底层算法及原理》。

更多精彩内容,敬请扫描下方二维码,关注我的微信公众号【Java觉浅】,获取第一时间更新哦!

http://weixin.qq.com/r/xx3v9_7EY7McraqU90jV (二维码自动识别)

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

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

相关文章

docker 删除包含关键字的镜像_30分钟带你轻松掌握Docker原理

前言Docker是什么&#xff1f;Docker是Go语言开发实现的容器。2013年发布至今&#xff0c;备受推崇。相关文档、学习资料十分详尽。近期有docker相关项目&#xff0c;得重新学习一下。博客以笔记为什么要使用 Docker&#xff1f;Docker 容器的启动在秒级Docker 对系统资源利用率…

pads中如何设置等长_如何在SQL Server中设置扩展,监控系统性能

dbForge Studio for SQL Server为有效的探索、分析SQL Server数据库中的大型数据集提供全面的解决方案&#xff0c;并设计各种报表以帮助作出合理的决策。dbForge Studio for SQL Server​www.evget.com扩展事件是一种有用且方便的解决方案&#xff0c;旨在监视您的系统性能。它…

iar stm32_STM32延时函数的四种方法

关注、星标公众号&#xff0c;不错过精彩内容单片机编程过程中经常用到延时函数&#xff0c;最常用的莫过于微秒级延时delay_us()和毫秒级delay_ms()。本文基于STM32F207介绍4种不同方式实现的延时函数。普通延时这种延时方式应该是大家在51单片机时候&#xff0c;接触最早的延…

使用pm2启动node文件_PM2 是什么

目录 pm2是什么特点示例说明配置文件常用命令背景 由于需要在容器云新增一个测试环境&#xff0c;改了代码相关的配置后&#xff0c;进行部署。发现服务一直启动不了。在和运维一起排查问题&#xff0c;他看到pm2的一些信息&#xff0c; 问我pm2是不是阻塞了&#xff0c;并不是…

CP/M世界上第一个微机操作系统

CP/M世界上第一个微机操作系统 微软宣布2014年4月8日将不再对Windows XP系统进行更新&#xff0c;宣告这个存活了13年的史上寿命最长的微机操作系统基本上寿终正寝。很多人都知道这是个脱胎于DOS的系统&#xff0c;也潜意识中认为DOS是微机操作系统的鼻祖。不过&#xff0c;这大…

安卓 usb音量调节_戴尔推出面向Teams和Zoom视频通话的USB-C免提适配器

COVID-19 大流行期间&#xff0c;许多企业将会议安排在了线上举办。为方便通过 Microsoft Teams 和 Zoom 之类云视讯平台进行沟通的笔记本电脑用户&#xff0c;戴尔特地推出了新款 USB-C 音频适配器。作为一款两用配件&#xff0c;MH3021P 不仅可以作为有线通话的免提适配器(集…

word表格美化技巧:如何统一改变表格的样式

在Word中插入的表格默认都是黑边白底&#xff0c;看上去非常的单调。比如这样&#xff1a; 很多小伙伴都是在新建表格并且填完数据之后&#xff0c;应用表格样式&#xff0c;来提升档次&#xff0c;如下&#xff1a; 但是&#xff0c;每次新建表格后再选择应用【表格样式】&…

banner信息是什么_我的设计成长笔记—第10篇(banner)

Banner2019年5月9日这里是我的设计成长笔记—————————————————Banner为什么单独拿出来聊因为我有差不多一年的时间都在做这个在我的成长过程中&#xff0c;banner是过渡从平面/美工到UI设计的一个过程。在这个过程中&#xff0c;我对设计的理解分成了三个部分第…

后台原理_电气控制原理动图22张,超赞!

今天从低压电器、电动机及控制线路、传感器及控制原理三部分来分享22张超赞的原理动图。低压电器部分1按钮开关2闸刀开关3行程开关4交流接触器5热继电器6时间继电器7速度继电器电动机及控制线路1异步电动机2直流电动机3步进电动机4永磁电机5正反转控制6自动往返控制7顺序控制8多…

[word技巧]把标题、图表题注编号由“一.1”改为“1.1“

一、问题描述 写作中文报告时&#xff0c;有时会要求一级标题用类似”第一章”的中文编号&#xff0c;二级标题用1.1这类编号&#xff0c;图表题注用“表1.1”的编号。此时&#xff0c;由于一级标题用的是中文数字&#xff08;如“一”&#xff09;作为序号&#xff0c;因此wor…

excel中怎样用公式获取表单控件_挑战高手:用不到 100 行代码,在前端实现 Excel 全部功能...

(点击图片获取专属你的开发工具)SpreadJS是一款基于 HTML5 的纯前端表格控件&#xff0c;兼容 450 种以上的 Excel 公式&#xff0c;具备“高性能、跨平台、与 Excel 高度兼容”的产品特性广受世界各地名企追捧。接下来让我们看看其具有哪些独特优势吧&#xff01;四大优势&…

vissim免修改时间工具_App闪退怎么办?免越狱如何安装未签名的App?

由于最近苹果大规模的封签名&#xff0c;导致在第三方渠道下载的软件都出现闪退没法使用的现象。目前的替代方法就是使用电脑端 Cydia Impactor 来给 App 进行自签&#xff0c;虽然相对比较麻烦&#xff0c;但这也是目前针对企业签名无法使用的唯一解决方法。下面以安装 FilzaE…

word表格美化技巧:如何统一改变表格的样式2+续表制作

一、表格样式 开始-样式-新建样式-样式类型&#xff1a;表格。 单独设置标题行&#xff0c;汇总行等格式即可。表格样式会显示在-设计-样式-表格样式中。 问题&#xff1a;汇总行无效。 即可。 二、续表 直接复制表格及题注到下一页&#xff0c;然后下下面表格的题注修改为…

excel条件格式详解

1、基于公式返回的逻辑值去判断&#xff0c;True则执行条件格式&#xff0c;FALSE不执行。 2、基于区域第一个单元格的公式&#xff0c;依次根据单元格引用方式判断区域内公式是否成立。 函数&#xff1a; 使用条件格式&#xff1a; 函数&#xff1a; 条件格式&#xff1a; 函…

ccf a类会议_CCF推荐 | 人工智能领域顶级会议:截稿日期批量速递

以下为已公布截稿日期的CCF推荐&#xff0c;人工智能领域会议&#xff0c;按照时间排序。个别会议因为没有公布截稿信息而不在所列时间线内。录取率信息为网络上可获得的最近年份数据&#xff0c;不一定是上一年的&#xff0c;文中尽量选择同时带有投稿量的数据年份供大家参考.…

python递归调用详解_Python递归调用自己的函数

原博文 2019-11-16 10:36 − def fact(x): if x 1: return 1 else: return x * fact(x-1) ...0191 相关推荐 2019-09-28 21:13 − Python python是一种跨平台的计算机程序设计语言&#xff0c;是一种面向对象的动态类型语言。 最初被设计用于编写自动化脚本(shell)&#xff0c…

vue跳转到外部链接_前端实战项目:Vue.js实现外卖平台webapp,饿了么项目的翻版...

链接&#xff1a;https://github.com/ljianshu/mt-app适合没有经验的朋友。项目涉及到技术栈&#xff1a;vue全家桶&#xff1a;Vue、Vue-router、Vue-cli等 组件化&#xff1a;单Vue文件 模块化&#xff1a;ES6 Module 第三方模块&#xff1a;better-scroll axios等 基础开发环…

令xtu3service开机时立即启动_Mac开机时可以使用的快捷键 苹果电脑快捷键使用介绍...

大家都知道所有电脑在开机时&#xff0c;按住一些按键可以访问一些功能&#xff0c;当然Mac电脑也不例外。苹果电脑通过在开机启动时按住一个或多个按键可以访问一些Mac功能和工具。如果各位用户使用这些开机键组合键中的任何一个&#xff0c;可在按下电源按钮后&#xff0c;重…

word 插入图片显示不全

word插入图片显示不全&#xff1a; 解决方案&#xff1a; 选中图片-段落-行距-选择单倍、或者多倍行距都可以。即可。