GC算法[通俗易懂]

GC算法[通俗易懂]JVM(JavaVirtualMachine) GC是什么?频繁收集Young区 较少收集Old区 基本不动Perm区  JVM在进行GC时,并非每次都对上面三个内存区域一起回收的,大部分时候回收的都是指新生代,因此GC按照回收的区域又分了两种类型,一种是普通GC(minorGC),一种是全局GC(majorGCorFullGC) 普通GC(…

大家好,又见面了,我是你们的朋友全栈君。

JVM(Java Virtual Machine) 

GC是什么?

  • 频繁收集 Young 区
  • 较少收集 Old 区
  • 基本不动 Perm 区

 GC算法[通俗易懂]

 

JVM在进行GC时,并非每次都对上面三个内存区域一起回收的,大部分时候回收的都是指新生代,因此GC按照回收的区域又分了两种类型,一种是普通GC(minor GC),一种是全局GC(major GC or Full GC)

 

  • 普通GC(minor GC):只针对新生代区域的GC
  • 全局GC(major GC or Full GC):针对年老代的GC,偶尔伴随对新生代的GC以及对永久代的GC。

GC的三大算法

其实还有一种:引用计数法,但是不用了。 

GC算法[通俗易懂]

复制算法:MinorGC(普通GC)

年轻代中使用的是 Minor GC,这种GC算法采用的是复制算法(Copying)

Minor GC会把Eden中的所有活的对象都移到 Survivor 区域中,如果 Survivor区中放不下,那么剩下的活的对象就被移到Oldgeneration中,也即一旦收集后,Eden是就变成空的了

当对象在Eden(包括一个 Survivor区域,这里假设是from区域)出生后,在经过一次 Minor GC后,如果对象还存活,并且能够被另外一块 Survivor区域所容纳(上面已经假设为from区域,这里应为to区域,即to区域有足够的内存空间来存储Eden和from区域中存活的对象),则使用复制算法将这些仍然还存活的对象复制到另外一块 Survivor区域(即to区域)中,然后清理所使用过的Eden以及 Survivor区域(即fom区域),并且将这些对象的年龄设置为1,以后对象在 Survivor区每熬过一次 Minor GC,就将对象的年龄+1,当对象的年龄达到某个值时(默认是15岁,通过  -XX:MaxTenuringThreshold 来设定参数),这些对象就会成为老年代。

 解释:

年轻代中的GC,主要是复制算法(Copying)

Hotspot JVM把年轻代分为了三部分:1个Eden区和2个 Survivor区(分别叫from和to)。默认比例为8:1:1,一般情况下,新创建的对象都会被分配到Eden区(一些大对象特殊处理),这些对象经过第一次 Minor GC 后,如果仍然存活,将会被移到Survivor区。对象在 Survivor区中每熬过一次 Minor GC ,年龄就会增加1岁,当它的年龄增加到一定程度时,就会被移动到年老代中。因为年轻代中的对象基本都是朝生夕死的(80%以上),所以在年轻代的垃圾回收算法使用的是复制算法,复制算法的基本思想就是将内存分为两块,每次只用其中一块,当这一块内存用完,就将还活着的对象复制到另外一块上面。复制算法不会产生内存碎片。

在GC开始的时候,对象只会存在于Eden区和名为“From”的 Survivor区,Survivor区”To“是空的。紧接着进行GC,Eden区中所有存活的对象都会被复制到“To”,而在“From”区中,仍存活的对象会根据他们的年龄值来决定去向。年龄达到一定值(年龄阈值,可以通过 -XX:MaxTenuringThreshold来设置)的对象会被移动到年老代中,没有达到阈值的对象会被复制到 “To”区域。经过这次GC后,Eden区和“From”区已经被清空。这个时候,“From”和“To”会交换他们的角色,也就是新的“To”就是上次GC前的“From”,新的“From”就是上次GC前的“To”。不管怎样,都会保证名为“To”的 Survivor区域是空的。Minor GC 会一直重复这样的过程,直到“To”区被填满,“To”区被填满之后,会将所有对象移动到年老代中。

GC算法[通俗易懂]

因为Eden区对象一般存活率较低,一般的,使用两块10%的内存作为空闲和活动区间,而另外80%的内存,则是用来给新建对象分配内存的。一旦发生GC,将10%(From)的活动区间与另外80%中存活的对象转移到10%(To)的空闲区间,接下来,将之前90%的内存全部释放,以此类推 。

口诀:

谁空谁是 to,复制要交换。

 总结:

  1. 优点:不会产生内存碎片,完整度极高。
  2. 缺点:浪费了这10%(To)的内存空间。

复制算法弥补了标记/清除算法中,内存布局混乱的缺点。不过与此同时,它的缺点也是相当明显的

  1. 它浪费了一半(1:1的这个一半,就是那10%)的内存,这太要命了。
  2. 如果对象的存活率很高,我们可以极端一点,假设是100%存活,那么我们需要将所有对象都复制一遍,并将所有引用地址重置一遍。复制这一工作所花费的时间,在对象存活率达到一定程度时,将会变的不可忽视。所以从以上描述不难看出,复制算法要想使用,最起码对象的存活率要非常低才行,而且最重要的是,我们必须要克服50%内存的浪费。

 


标记清除/标记整理算法:FullGC又叫 MajorGC(全局GC)

 老年代一般是由标记清除或者是标记清除标记整理的混合实现

标记清除(Mark-Sweep)

GC算法[通俗易懂]

 GC算法[通俗易懂]

 GC算法[通俗易懂]

 GC算法[通俗易懂]

缺点: 

  1. 首先,它的缺点就是效率比较低(递归与全堆对象遍历),而且在进行GC的时候,需要停止应用程序,这会导致用户体验非常差劲。
  2. 其次,主要的缺点则是这种方式清理出来的空闲内存是不连续的,这点不难理解,我们的死亡对象都是随机的出现在内存的各个角落的,现在把它们清除之后,内存的布局自然会乱七八糟。而为了应付这一点,JVM 就不得不维持一个内存的空闲列表,这又是一种开销。而且在分配数组对象的时候,寻找连续的内存空间会不太好找。

标记整理(Mark-Compact)

 GC算法[通俗易懂]

注释:上面标记的是活的。 

 GC算法[通俗易懂]

 GC算法[通俗易懂]

 GC算法[通俗易懂]

 缺点:

  1. 标记/整理算法唯一的缺点就是效率也不高,不仅要标记所有存活对象,还要整理所有存活对象的引用地址。从效率上来说,标记/整理算法要低于复制算法。

 


小结:

  • 内存效率:复制算法>标记清除算法>标记整理算法(此处的效率只是简单的对比时间复杂度,实际情况不一定如此)
  • 内存整齐度:复制算法=标记整理算法>标记清除算法
  • 内存利用率:标记整理算法=标记清除算法>复制算法

可以看出,效率上来说,复制算法是当之无愧的老大,但是却浪费了太多内存,而为了尽量兼顾上面所提到的三个指标,标记/整理算法相对来说更平滑一些,但效率上依然不尽如人意,它比复制算法多了一个标记的阶段,又比标记/清除多了一个整理内存的过程。

难道就没有一种最优算法吗?

回答:无,没有最好的算法,只有最合适的算法。==========>分代收集算法(根据 JVM 不同的(新生、养老、永久)带,采用各自不同的算法)


面试题:

1. JVM内存模型以及分区,需要详细到每个区放什么。

2. 堆里面的分区:Eden,survival  from  to,老年代,各自的特点。

3. GC的三种收集方法:标记清除、标记整理、复制算法的原理与特点,分别阐述。

4. Minor GC 与 Full GC 分别在什么时候发生。

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/148274.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Java多线程常用面试题(含答案,精心总结整理)

    Java多线程常用面试题(含答案,精心总结整理)Java并发编程问题是面试过程中很容易遇到的问题,提前准备是解决问题的最好办法,将试题总结起来,时常查看会有奇效。现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行?这个线程问题通常会在第一轮或电话面试阶段被问到,目的是检测你对”join”方法是否熟悉。这个多线程问题比较简单,可以用join方法实现。核心:thread.Jo

    2022年7月15日
    18
  • Android 开发(三)数据库存储

    Android 开发(三)数据库存储

    2021年8月26日
    44
  • ICMP报文详解

    ICMP报文详解概述ICMP允许主机或路由报告差错情况和提供有关异常情况。ICMP是因特网的标准协议,但ICMP不是高层协议,而是IP层的协议。通常ICMP报文被IP层或更高层协议(TCP或UDP)使用。一些ICMP报文把差错报文返回给用户进程。ICMP报文作为IP层数据报的数据,加上数据报的首部,组成数据报发送出去。ICMP报文的种类有两种,即ICMP差错报告报文和ICMP询问报文。ICMP报文的格式类型:占8位代码:占8位检验和:占16位说明:ICMP所有报文的前4个.

    2022年6月11日
    511
  • 使用Diskgenius将U盘分区,分为启动盘和文件存储两大功能详解

    使用Diskgenius将U盘分区,分为启动盘和文件存储两大功能详解DiskGenius是一款集分区办理与数据规复功效的东西软件。它是在最初的DOS版的底子上开辟而成的。准备工作:1.DiskGenius软件2.带有系统的U盘(我是用ULtraISO软件将ISO镜像写入到U盘的,方法:http://jingyan.baidu.com/article/a948d651b0f6a20a2dcd2eae.html)3.电脑第一步:将U盘中的系

    2022年8月11日
    30
  • 视屏剪辑软件 & free video editor

    视屏剪辑软件 & free video editor视屏剪辑软件&freevideoeditorpurposeaddanimationkeyframetotutorialsvideovlogdemostutorial

    2022年6月30日
    23
  • Java中的map集合顺序如何与添加顺序一样

    Java中的map集合顺序如何与添加顺序一样一般使用map用的最多的就是hashmap,但是hashmap里面的元素是不按添加顺序的,那么除了使用hashmap外,还有什么map接口的实现类可以用呢?这里有2个,treeMap和linkedHashMap,但是,要达到我们的要求:按添加顺序保存元素的,就只有LinkedHashMap。下面看运行的代码。packagecom.lxk.collectionTest;impor…

    2022年5月30日
    104

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号