【JAVAEE】JVM中垃圾回收机制 GC

这篇具有很好参考价值的文章主要介绍了【JAVAEE】JVM中垃圾回收机制 GC。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

 【JAVAEE】JVM中垃圾回收机制 GC,JavaEE初阶,jvm,java-ee,java

  • 博主简介:想进大厂的打工人
  • 博主主页:@xyk:
  • 所属专栏: JavaEE初阶 

上篇文章我们讲了java运行时内存的各个区域。

传送门:【JavaEE】JVM的组成及类加载过程_xyk:的博客-CSDN博客

对于程序计数器、虚拟机栈、本地方法栈这三部分区域而言,其生命周期与相关线程有关,随线程而生,随线程而灭。并且这三个区域的内存分配与回收具有确定性,因为当方法结束或者线程结束时,内存就自然跟着线程回收了。因此我们本篇所讲的有关内存分配和回收关注的为Java堆与方法区这两个区域。


目录

文章目录

一、垃圾回收机制—GC

1.1 引用计数器算法(java没有采用这种算法)

1.2 可达性分析

二、垃圾回收算法

2.1 标记清除算法

2.2 复制算法

2.3 标记整理算法

2.4 复合策略”分带回收“

三、垃圾收集器

3.1 CMS收集器(老年代收集器,并发GC)

3.2 G1收集器(唯一一款全区域的垃圾回收器)


一、垃圾回收机制—GC

在JVM中存在一个垃圾回收机制,GC,帮助程序猿自动释放内存的,能够有效的减少内存泄漏的出现频率。主要是针对 堆上的对象 来进行释放~

GC也就是以 对象 为单位进行释放的(说是释放内存,其实是释放对象)

【JAVAEE】JVM中垃圾回收机制 GC,JavaEE初阶,jvm,java-ee,javaGC中主要分成两个阶段:

1.找,谁是垃圾

2.释放,用什么算法

Java堆中存放着几乎所有的对象实例,垃圾回收器在对堆进行垃圾回收前,首先要判断这些对象哪些还存活,哪些已经"死去"。判断对象是否已"死"有如下几种算法

死亡对象的判断算法:

1.1 引用计数器算法(java没有采用这种算法)

引用计算器判断对象是否存活的算法是这样的:给每一个对象设置一个引用计数器,每当有一个地方引用这个对象的时候,计数器就加1,与之相反,每当引用失效的时候就减1。当计数器为0,则认为没有对象了,就是垃圾了~

优点:实现简单、性能高。

缺点:增减处理频繁消耗cpu计算、计数器占用很多位浪费空间(每个对象都需要分配一个计数器)、最重要的缺点是无法解决循环引用的问题。

什么是循环引用?

存在两个对象,同时互相引用指向对象

【JAVAEE】JVM中垃圾回收机制 GC,JavaEE初阶,jvm,java-ee,java

 【JAVAEE】JVM中垃圾回收机制 GC,JavaEE初阶,jvm,java-ee,java

此时,如果a和b都销毁了,这个时候,两个对象的引用计数给自减1,但是这两个对象的引用计数不是0,不能作为垃圾,无法回收,这俩个对象也无法使用了~陷入了一个逻辑上的循环

1.2 可达性分析

把对象之间的引用关系,理解成了一个树形结构,从一些特殊的起点出发,进行遍历,只要能遍历访问到的对象,就是”可达“,再把”不可达的“当作垃圾回收即可

【JAVAEE】JVM中垃圾回收机制 GC,JavaEE初阶,jvm,java-ee,java

通过 root 这个引用,就可以访问到整个树的任意结点,那么哪些对象可以作为gcroot?

  1. 栈上的局部变量(每个栈的每个局部变量,都是起点)
  2. 常量池中的引用的对象
  3. 方法区中,静态成员引用的对象

可达性分析,克服了引用计数的两个缺点~

但是也有自己的问题:

1.消耗更多的时间,因此某个对象成了垃圾,也不一定第一时间发现,每次扫描的过程,都是需要消耗时间的

2.在进行可达性分析的时候,要顺藤摸瓜,一旦这个过程中,代码的对象引用关系发生变化了,就麻烦了

因为,为了更准确的完成这个”摸瓜“的过程,需要让其他的业务线程 暂停工作!!(STW问题

stop the world,为了保证内存的一致性,必须先暂停程序的执行)

二、垃圾回收算法

上面我们可以通过可达性分析找到垃圾,那么我们应该用什么回收算法来进行回收操作呢?

2.1 标记清除算法

标记-清除算法是最基础的算法,像它的名字一样算法分为“标记”和“清除”两个阶段,首先需要标记出所需要回收的对象,标记完成后统一收集被标记的对象。

【JAVAEE】JVM中垃圾回收机制 GC,JavaEE初阶,jvm,java-ee,java

优点: 实现简单。

缺点: 产生不连续的内存碎片;“标记”和“清除”的执行效率都不高。如果要申请空间比较大,会失败。

2.2 复制算法

"复制"算法是为了解决"标记-清理"的效率问题。它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这块内存需要进行垃圾回收时,会将此区域还存活着的对象复制到另一块上面,然后再把已经使用过的内存区域一次清理掉。

【JAVAEE】JVM中垃圾回收机制 GC,JavaEE初阶,jvm,java-ee,java

 

优点: 执行效率高。

缺点: 空间利用率低, 因为复制算法每次只能使用一半的内存。

2.3 标记整理算法

类似于 顺序表删除中间元素,有一个搬运过程~
 

【JAVAEE】JVM中垃圾回收机制 GC,JavaEE初阶,jvm,java-ee,java

优点: 解决了内存碎片问题,比复制算法空间利用率高。

缺点: 因为有局部对象移动,相对效率不高。

2.4 复合策略”分带回收“

因此,实际上 JVM 的实现思路,是结合了上述几种思想方法,针对不同的情况,使用不同的策略.

给对象设定了”年龄“这样的概念,描述了这个对象存在多久了,如果一个对象刚诞生,认为是0岁,每次经过一轮扫描,没被标记成垃圾,这个时候对象就涨一岁,通过年龄来区分这个对象的 存活时间

【JAVAEE】JVM中垃圾回收机制 GC,JavaEE初阶,jvm,java-ee,java

1.新创建的对象,放到伊甸区,当垃圾回收扫描伊甸区之后,绝大部分对象都会在第一轮 GC 中就被干掉~~ 大部分对象是活不过一岁的,朝生夕死

2.如果伊甸区的对象,熬过第一轮 GC ,就会通过复制算法,拷贝到幸存区,幸存区分成两半大小,一次只使用其中的一半~~ 垃圾回收扫描幸存区的对象,也是发现垃圾就淘汰,不是垃圾的,通过复制算法,复制到幸存区的另外一半

3.当这个对象在幸存区,熬过若干轮 GC 之后,年龄增长到一定程度了,就会通过复制算法拷贝到老年代

4.进入老年代的对象,年龄都很大了,再消亡的概率比前面新生代中的对象小,针对老年代 GC 的扫描频次就会降低很多,如果老年代发现某个对象是垃圾了,使用标记整理的方式清除

5.特殊情况,如果对象非常大,直接进入老年代(大对象进行复制算法,成本比较高,而且大对象也不会很多)

三、垃圾收集器

3.1 CMS收集器(老年代收集器,并发GC)

特性:
CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。目前
很大一部分的Java应用集中在互联网站或者B/S系统的服务端上,这类应用尤其重视服务的响应速
度,希望系统停顿时间最短,以给用户带来较好的体验。CMS收集器就非常符合这类应用的需求。
CMS收集器是基于“标记—清除”算法实现的,它的运作过程相对于前面几种收集器来说更复杂一些,整个过程分为4个步骤:

初始标记(CMS initial mark)
初始标记仅仅只是标记一下GC Roots能直接关联到的对象,速度很快,需要“Stop The
World”。


并发标记(CMS concurrent mark)
并发标记阶段就是进行GC Roots Tracing的过程。


重新标记(CMS remark)
重新标记阶段是为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分
对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的
时间短,仍然需要“Stop The World”。


并发清除(CMS concurrent sweep)
并发清除阶段会清除对象

由于整个过程中耗时最长的并发标记和并发清除过程收集器线程都可以与用户线程一起工作,所以,从总体上来说,CMS收集器的内存回收过程是与用户线程一起并发执行的

缺点:

  1. CMS收集器对CPU资源非常敏感
  2. CMS收集器无法处理浮动垃圾 
  3. CMS收集器会产生大量空间碎片

【JAVAEE】JVM中垃圾回收机制 GC,JavaEE初阶,jvm,java-ee,java

 

3.2 G1收集器(唯一一款全区域的垃圾回收器)

G1(Garbage First)垃圾回收器是用在heap memory很大的情况下,把heap划分为很多很多的
region块,然后并行的对其进行垃圾回收

G1垃圾回收器回收region(区域)的时候基本不会STW,而是基于 most garbage优先回收(整体来看是基于"标记-整理"算法,从局部(两个region之间)基于"复制"算法) 的策略来对region进行垃圾回收的。
【JAVAEE】JVM中垃圾回收机制 GC,JavaEE初阶,jvm,java-ee,java

一个region有可能属于Eden,Survivor或者Tenured内存区域。图中的E表示该region属于Eden内存区域,S表示属于Survivor内存区域,T表示属于Tenured内存区域。图中空白的表示未使用的内存空间。G1垃圾收集器还增加了一种新的内存区域,叫做Humongous内存区域,如图中的H块。这种内存区域主要用于存储大对象-即大小超过一个region大小的50%的对象

1.年轻代垃圾收集
在G1垃圾收集器中,年轻代的垃圾回收过程使用复制算法。把Eden区和Survivor区的对象复制到新的Survivor区域
【JAVAEE】JVM中垃圾回收机制 GC,JavaEE初阶,jvm,java-ee,java

 2.老年代垃收集

1.初始标记(Initial Mark)阶段 - 同CMS垃圾收集器的Initial Mark阶段一样,G1也需要暂停应用程序的执行,它会标记从根对象出发,在根对象的第一层孩子节点中标记所有可达的对象。

2.并发标记(Concurrent Mark)阶段 - 在这个阶段G1做的事情跟CMS一样。但G1同时还多做了一件事情,就是如果在Concurrent Mark阶段中,发现哪些Tenured region中对象的存活率
很小或者基本没有对象存活,那么G1就会在这个阶段将其回收掉,而不用等到后面的clean
up阶段。
 

3.最终标记(CMS中的Remark阶段) - 在这个阶段G1做的事情跟CMS一样, 但是采用的算法不
同,G1采用一种叫做SATB(snapshot-at-the-begining)的算法能够在Remark阶段更快的标
记可达对象。

4.筛选回收(Clean up/Copy)阶段 - 在G1中,没有CMS中对应的Sweep阶段。相反 它有一个
Clean up/Copy阶段,在这个阶段中,G1会挑选出那些对象存活率低的region进行回收,这个
阶段也是和minor gc一同发生的,如下图所示

【JAVAEE】JVM中垃圾回收机制 GC,JavaEE初阶,jvm,java-ee,java

G1(Garbage-First)是一款面向服务端应用的垃圾收集器。HotSpot开发团队赋予它的使命是未来可以替换掉JDK 1.5中发布的CMS收集器。 如果你的应用追求低停顿,G1可以作为选择;如果你的应用追求吞吐量,G1并不带来特别明显的好处。 文章来源地址https://www.toymoban.com/news/detail-577225.html

到了这里,关于【JAVAEE】JVM中垃圾回收机制 GC的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • JVM解密: 解构类加载与GC垃圾回收机制

    JVM 其实是一个 Java 进程,该进程会从操作系统中申请一大块内存区域,提供给 Java 代码使用,申请的内存区域会进一步做出划分,给出不同的用途。 其中最核心的是栈,堆,方法区这几个区域: 堆,用来放置 new 出来的对象,类成员变量。 栈,维护方法之间的调用关系,放

    2024年02月10日
    浏览(44)
  • 【JVM】垃圾回收 GC

    垃圾回收(Garbage Collection,GC)是由 Java 虚拟机(JVM)垃圾回收器提供的一种对内存回收的一种机制,它一般会在内存空闲或者内存占用过高的时候对那些没有任何引用的对象不定时地进行回收。以避免内存溢出和崩溃的问题。JVM的垃圾回收算法包括引用类型、引用计数器法

    2024年01月16日
    浏览(49)
  • 【JVM】JVM垃圾回收GC相关参数说明

    -XX:+PrintCommandLineFlags : 输出JVM启动参数 -XX:+UseSerialGC :在新生代和老年代使用串行收集器 -XX:SurvivorRatio :设置eden区大小和survivior区大小的比例 -XX:NewRatio :新生代和老年代的比 -XX:+UseParNewGC :在新生代使用并行收集器 -XX:+UseParallelGC :新生代使用并行回收收集器 -XX:+UseParallelO

    2024年02月04日
    浏览(46)
  • JVM----GC(垃圾回收)详解

    Automatic Garbage Collection (自动垃圾回收)是JVM的一个特性,JVM会启动相关的线程,该线程会轮训检查heap memeory,并确定哪些是未被引用的(unreferenced),即未被使用的;哪些是被引用的(referenced),即正在使用的。 在C/C++语言中,对象内存的分配与回收,是手动进行分配与回收

    2024年02月09日
    浏览(47)
  • 02JVM_垃圾回收GC

    在 堆 里面存放着java的所有对象实例,当对象为“死去”,也就是不再使用的对象,就会进行垃圾回收GC 1.1引用计数器 介绍 在对象中添加一个引用计数器,当一个对象被其他变量引用时这个对象的引用计数器加1。当某个变量不再引用这个对象时引用计数器减1。当这个引用计

    2024年02月09日
    浏览(39)
  • 【Java】图解 JVM 垃圾回收(一):GC 判断策略、引用类型、垃圾回收算法

    垃圾 是指运行程序中 没有任何引用指向的对象 ,需要被回收。 内存溢出 :经过垃圾回收之后,内存仍旧无法存储新创建的对象,内存不够溢出。 内存泄漏 :又叫 “ 存储泄漏 ”,对象不会再被程序使用了,但是 GC 又不能回收它们。例如:IO 流不适用了但是没有被 Close、

    2024年02月19日
    浏览(50)
  • JVM基础知识(内存区域划分,类加载,GC垃圾回收)

    目录 内存区域划分 JVM中的栈 JVM中的堆 程序计数器 方法区(元数据区) 给一段代码,某个变量在哪个区域上? 类加载 类加载时机 双亲委派模型 GC 垃圾回收机制 GC 实际工作过程 1.找到垃圾/判定垃圾 1.可达性分析(Java中的做法) 2.引用计数 2.清理垃圾 1.标记清除 2.复制算法 3.标记整

    2024年02月07日
    浏览(65)
  • 【JavaEE初阶】了解JVM

    JVM启动的时候,会申请到一整个很大的内存区域.JVM是一个应用程序,要从操作系统里申请内存.JVM就根据需要,把空间分为几个部分,每个部分各自有不同的功能.具体划分如下: Native Method Stacks(本地方法栈) :native表示是JVM内部的C++代码.就是给调用native方法(JVM内部的方法)准备的栈空

    2024年02月13日
    浏览(59)
  • 小研究 - 浅析 JVM 中 GC 回收算法与垃圾收集器

    本文主要介绍了JVM虚拟机中非常重要的两个部分,GC 回收算法和垃圾收集器。从可回收对象的标记开始,详细介绍 了四个主流的GC算法,详细总结了各自的算法思路及优缺点, 提出了何种情况下应该通常选用哪种算法。 目录 1 标记可回收对象 1.1 引用计数器 1.2 可达性分析

    2024年02月14日
    浏览(41)
  • 《JavaEE初阶》JVM基础知识

    本章主要介绍JVM中比较重要的三个内容: JVM内存区域划分 JVM类加载机制 JVM垃圾回收机制 当我们创建一个java进程时,启动时会向操作系统申请一块内存,JVM会将这块内存划分为几个区域: 堆 栈 程序计数器 方法区 堆: 堆上主要存放的是new的对象,是最重要的区域,也是内存划分最多

    2024年02月09日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包