根可达算法的根_我的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开放的端口_docker-5-解决宿主机没有开放81端口却可以直接访问docker启动的81端口nginx容器的问题...

我以为经过前面四篇博文的学习&#xff0c;自己对docker的了解最起码入门了&#xff0c;但是当我用docker启动一个81端口的nginx后(宿主机:容器/81:80)&#xff0c;在宿主机的firwall防火墙没有添加81端口的情况下&#xff0c;竟然可以直接访问成功&#xff0c;然后试下docker运…

测试计划与测试方案

测试计划与测试方案主要有以下几点区别&#xff1a; 1.测试计划是一个偏管理性质的文档&#xff0c;而测试方案是一个偏技术类型的文档&#xff1b; 2.测试计划通俗来讲就是解决【谁来做&#xff1f;】【做什么&#xff1f;】的问题&#xff0c;而测试方案是解决【怎么做&#…

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

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

ssm访问不到html_IDEA解决SSM项目的静态资源路径问题:HTML,CSS,JS--详解

直接上图(项目目录结构)&#xff1a;我们主要关注webapp。如上图&#xff0c;建议把js&#xff0c;css&#xff0c;layui&#xff0c;首页等文件放在WEB-INF外部&#xff0c;WEB-INF放程序的主要网页&#xff0c;index页面&#xff0c;welcome&#xff0c;各种管理页面等(如下图…

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

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

string循环输入,Ctrl+z截止

注意1&#xff1a;while和循环的位置问题&#xff1a;若while在for循环里&#xff0c;则for循环一次&#xff0c;就会使while中的语块一直执行&#xff0c;CtrlZ结束后&#xff0c;只会给s[0]赋值。 注意2&#xff1a;i的值即为string数组的实际值 #include<iostream> …

testmeshpro合批_TextMesh Pro Emoji Align With Text(表情和文字对齐)

前言MMO游戏中需要富文件组件&#xff0c;大体功能包括图文混排&#xff0c;表情&#xff0c;超链接&#xff0c;文字动画等富文本功能&#xff0c;且DC数占用少。本文选择Unity免费提供的TextMesh Pro 解决方案。软件环境Unity3D 5.3.7p4TextMesh Pro 1.0.555.0b11(Jul 06.201…

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 不仅可以作为有线通话的免提适配器(集…

python试卷河南理工大学万方科技学院_河南理工大学万方科技学院

河南理工大学具有百年办学历史&#xff0c;是一所拥有博士学位授予权的省重点建设的骨干高校。其前身焦作路矿学堂是我国历史上第一所路矿高等学府&#xff0c;是河南省建立最早的高等学校&#xff0c;是我国路矿、工矿高端人才的摇篮&#xff0c;也是中国矿业大学的前身。在学…

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;四大优势&…

python3 虚拟环境 pip 版本_【python知识】 - Python3之PIPENV虚拟环境及封装

Python的封装是通过pyinstaller直接打包python环境下的所有第三方模块&#xff0c;不管是不是封装程序涉及到的模块通通都一股脑打包进来&#xff0c;造成封装后大小超出预计很多。Pipenv 是一款管理虚拟环境的命令行软件&#xff0c;简单来讲&#xff0c;它可以创建一个只在某…

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

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