首页 > 其他分享 >JVM垃圾回收(一)

JVM垃圾回收(一)

时间:2022-12-14 11:14:02浏览次数:96  
标签:标记 对象 清除 回收 存活 复制 垃圾 JVM 内存

参考资料:
https://shuyi.tech/archives/jvm-serial-08-jvm-garbage-collection
https://zhuanlan.zhihu.com/p/112018694

判断哪些是垃圾

现今 Java 虚拟机判断垃圾对象使用的是:GC Root Tracing 算法(根搜索算法)。其大概的过程是这样:从 GC Root 出发,所有可达的对象都是存活的对象,而所有不可达的对象都是垃圾。


通过一系列名为”GCRoots”的对象作为起始点,从这个节点向下搜索,搜索走过的路径称为ReferenceChain,当一个对象到GCRoots没有任何ReferenceChain相连时,则证明这个对象不可用。
image


其实 GC Root 就是一组活跃引用的集合,这些集合是经过特意筛选出来的,通常包括: - 所有当前被加载的 Java 类 - Java 类的引用类型静态变量 - Java类的运行时常量池里的引用类型常量 - VM的一些静态数据结构里指向GC堆里的对象的引用 - 等等 简单地说,GC Root 就是经过精心挑选的一组活跃引用,这些引用是肯定存活的。那么通过这些引用延伸到的对象,自然也是存活的。

垃圾回收算法

垃圾回收算法简单地说有三种算法:标记清除算法、复制算法、标记整理算法。

标记清除法

在标记阶段,标记所有由 GC Root 触发的可达对象,所有未被标记的对象就是垃圾对象。之后在清除阶段,清除所有未被标记的对象。
image

标记清除优势

  • 标记清除法的特点就是简单直接,速度也非常快,适合存活对象多,需要回收的对象少的场景。

标记清除不足

  • 1、会造成不连续的内存空间:就像上图清除后的内存区域一样,清除后内存会有很多不连续的空间,这也就是我们常说的空间碎片,这样的空间碎片太多不仅不利于我们下次分配,而且当有大对象创建的时候,我们明明有可以容纳的总空间,但是空间都不是连续的造成对象无法分配,从而不得不提前触发GC。

  • 2、性能不稳定:内存中需要回收的对象,当内存中大量对象都是需要回收的时候,通常这些对象可能比较分散,所以清除的过程会比较耗时,这个时候清理的速度就会比较慢了。

标记复制法

标记清除法最大问题是会造成空间碎片,同时可回收对象如果太多也会影响其性能,而标记复制法则可以解决这两大问题。标记清除法的关注点在可回收的对象身上,而标记复制法的关注点则放在了存活的对象身上,通过把存活的对象转移到一个新的区域,然后对原区域的对象进行统一清理。


首先它把内存划分出三块区域,一块用于存放新创建的对象叫Eden区,另外两块则用于存放存活的对象分别叫 S1区和S2区。回收的时候会有两种情况,一种是把Eden和S1区的存活对象复制到S2区,第二种是把Eden和S2区的存活对象复制到S1区 ,也就是说S1区和S2这两块区域同时只会有一块使用,通过这种方式保证始终会有一块空白的q区域用于下次GC时存放存活的对象,而且原来的区域不需要考虑保留存活的对象,所以可以直接一次性清除所有对象,这要既简单直接同时也保证了清除的内存区域的内存连续性。

image

标记复制法的优势:
标记复制法解决了标记清除法的空间碎片问题,并且采用移动存活对象的方式,每次清除针对的都是一整块内存,所以清除可回收对象的效率也比较高,但因为要移动对象所以这里会耗费一部分时间,所以标记复制法效率还是会低于标记清除法。

标记复制法的不足:

  • 1、会浪费一部分空间:通过上面的图我们也不难发现,总是会有一块空闲的内存区域是利用不到的,这也造成了资源的浪费。

  • 2、存活对象多会非常耗时:因为复制移动对象的过程是比较耗时的,这个不仅需要移动对象本身,还需要修改使用了这些对象的引用地址,所以当存活对象多的场景会非常耗时,所以标记复制法比较适合存活对象较少的场景。

  • 3、需要担保机制:因为复制区总会有一块空间的浪费,而为了减少浪费空间太多,所以我们会把复制区的空间分配控制在很小的区间,但是空间太小又会产生一个问题,就是在存活的对象比较多的时候,这时复制区的空间可能不够容纳这些对象,这时就需要借一些空间来保证容纳这些对象,这种从其他地方借内存的方式我们称它为担保机制。

标记整理法

标记整理法分为标记和整理两个阶段,标记阶段会先把存活的对象和可回收的对象标记出来;标记完再对内存对象进行整理,这个阶段会把存活的对象往内存的一端移动,移动完对象后再清除存活对象边界之外的对象。
image

标记整理法的优势:

  • 标记整理法是解决了标记复制法浪费空间、不适合存活对象多场景的短板,又解决了标记清除法空间碎片的短板, 所以对于标记复制法不适合的场景,同时又不能忍受标记清除法的空间碎片问题,就可以考虑标记整理法。

标记整理法的不足:

  • 没有任何一种算法是万能的,标记整理法看似解决了很多问题,但它本身存在很严重的性能问题,标记整理法是三种垃圾回收算法中性能最低的一种,因为标记整理法在移动对象的时候不仅需要移动对象,还要额外的维护对象的引用的地址,这个过程可能要对内存经过几次的扫描定位才能完成,同时还有清除对象的空座,既然做的事情这么多那么必然消耗的时间也越多。

垃圾回收算法的适用场景

1、标记清除法

特点: 简单、收集速度快,但会有空间碎片,空间碎片会导致后面的GC频率增加。
适合场景:只有小部分对象需要进行回收的,所以标记清除法比较适用于老年代的垃圾回收,因为老年代一般存活对象会比回收对象要多。

2、标记复制法

特点:收集速度快,可以避免空间碎片,但是有空间浪费,存活对象较多的情况下复制对象的过程等会非常耗时,而且需要担保机制。

适合场景: 只有少量对象存活的场景,这也正是新生代对象的特点,所以一般新生代的垃圾回收器基本都会选择标记复制法。

3、标记整理法

特点: 相对于标记复制法不会浪费内存空间,相对标记清除法则可以避免空间碎片,但是速度比其他两个算法慢。

适合场景: 内存吃紧,又要避免空间碎片的场景,老年代想要避免空间碎片问题的话通常会使用标记整理法。

分代思想 & 分区思想

所谓分代思想,就是根据 JVM 内存的不同内存区域,采用不同的垃圾回收算法。例如对于存活对象少的新生代区域,比较适合采用复制算法。这样只需要复制少量对象,便可完成垃圾回收,并且还不会有内存碎片。而对于老年代这种存活对象多的区域,比较适合采用标记压缩算法或标记清除算法,这样不需要移动太多的内存对象。

分代思想按照对象的生命周期长短将其分为了两个部分(新生代、老年代),但 JVM 中其实还有一个分区思想,即将整个堆空间划分成连续的不同小区间。
每一个小区间都独立使用,独立回收,这种算法的好处是可以控制一次回收多少个区间,可以较好地控制 GC 时间。

标签:标记,对象,清除,回收,存活,复制,垃圾,JVM,内存
From: https://www.cnblogs.com/d111991/p/16981474.html

相关文章

  • Java性能调优System的gc垃圾回收方法
    java性能调优System的gc垃圾回收方法java性能调优System的gc垃圾回收方法示例解一、什么是System.gc()?​​System.gc()​​是用Java,C#和许多其他流行的高级编程语言提供的API......
  • 知识回顾-JDK有哪些垃圾收集器及收集器组合
    目录经典垃圾收集器新生代Serial收集器ParNew收集器ParallelScavenge收集器老年代SerialOld收集器ParallelOld收集器CMS收集器G1收集器ZGC收集器如何获取使用的默认的垃......
  • 【JVM】Java 通过 javap 命令分析java汇编指令
      javap是jdk自带的反解析工具。它的作用就是根据class字节码文件,反解析出当前类对应的code区(汇编指令)、本地变量表、异常表和代码行偏移量映射表、常量池等等信息。当然......
  • 【JVM】VisualVM Java程序性能分析工具
     【JVM】VisualVMJava程序性能分析工具 介绍VisualVM是一个集成多个JDK命令行工具的可视化工具。可以作为Java应用程序性能分析和运行监控的工具。开发人员可以利用它来......
  • KingbaseES垃圾回收参数优化之maintenance_work_mem
    maintenance_work_mem参数说明与vacuum过程maintenance_work_mem,autovacuum_work_mem。如果没有设置autovacuum_work_mem,默认值是-1,则使用maintenance_work_mem的设......
  • 解读JVM级别本地缓存Caffeine青出于蓝的要诀2 —— 弄清楚Caffeine的同步、异步回源方
    大家好,又见面了。本文是笔者作为掘金技术社区签约作者的身份输出的缓存专栏系列内容,将会通过系列专题,讲清楚缓存的方方面面。如果感兴趣,欢迎关注以获取后续更新。上......
  • JVM类的加载机制
    1类的加载机制的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的......
  • 朴素贝叶斯——实现垃圾邮件分类
    一、贝叶斯定理贝叶斯定理由英国数学家贝叶斯(ThomasBayes1702-1761)发展,用来描述两个条件概率之间的关系,比如P(A|B)和P(B|A)。按照乘法法则,可以立刻导出:P(A∩B......
  • JVM入门
    浅谈jvm面试题请你谈谈你对JVM的理解?java8虚拟机和之前的变化更新?什么是00M,什么是栈溢出StackOverFlowError?怎么分析?JVM的常用调优参数有哪些?内存快照如何抓......
  • 10个经典又容易被人疏忽的JVM面试题
    1.对象一定分配在堆中吗?有没有了解逃逸分析技术?「对象一定分配在堆中吗?」不一定的,JVM通过「逃逸分析」,那些逃不出方法的对象会在栈上分配。「什么是逃逸分析?」逃逸分析(E......