• 【JVM】垃圾回收机制详解(GC)


    一.GC的作用区域

    可以看jvm详解之后,再来理解这篇文章更好

    堆和方法区,主要发生在堆中,然后主要发生在堆的伊甸园区(Eden)。

    二.关于对象是否可回收

    1.可达性分析算法和引用计数算法

    Java中的垃圾回收是根据可达性分析算法(Reachability Analysis)引用计数算法来判断对象是否存活的。

    可达性分析算法:
    	简单来说这个算法的就是根据"GC Roots"对象为根,向下去搜索(去找叶节点),
    搜索走过的路径叫引用链(Reference Chain),当一个对象和"GC Roots"之间没有
    任何引用链时,这个对象就会判定为可回收的。
    	下面示意图,因为"GC Root"有路径可以到达对象1到5,所以对象1到5是不可回
    收的,然而"GC Root"没有任何路径可以到达对象6到8,所以对象6到8就是可回收的。
    
    java中可作为"GC Roots"的对象:
    (1)虚拟机栈中引用的对象
    (2)本地方法栈内 JNI(本地方法,就是被native修饰的方法)引用的对象
    (3)方法区中类静态属性引用的对象
    (4)方法区中常量引用的对象
    
    引用计数器算法:
    	就是为每个对象都添加一个计数器,每多一个引用指向对象,计数器就加1,当计数器为0的对象,就是可回收的对象。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述

    2.四种引用类型

    JDK.1.2 之后,Java 对引用的概念进行了扩充,将引用分为了:强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)4 种,这 4 种引用的强度依次减弱。

    • 强引用

    强引用的对象回收基于“可达性分析”算法,当对象不可达时才可能会被回收。就算jvm内存满了,会抛出OutOfMemoryErro,也不会回收强引用。例如:

    Object obj=new Object(); //手动把对象置为null,jvm就会回收对象。

    • 软引用

    软引用是说一些有用但是非必需的对象。在jvm内存即将满的时候,会将软引用关联的对象,进行回收,如果回收之后,内存还是不够,才会抛出OutOfMemoryErro。

    JDK1.2之后,提供了SoftReference类来实现软引用。例如:

    SoftReference ref = new SoftReference(refObj);

    • 弱引用

    无论内存是否足够,只要 JVM 开始进行垃圾回收,那些被弱引用关联的对象都会被回收。

    JDK1.2之后,提供了WeakReference类来实现弱引用。例如:

    WeakReference ref = new WeakReference(refObj);

    • 虚引用

    虚引用是最弱的一种引用关系,如果一个对象仅持有虚引用,那么它就和没有任何引用一样,随时可能会被回收

    JDK1.2之后,提供了PhantomReference类来实现虚引用(构造的时候,需要指定一个队列)。例如:

    ReferenceQueue referenceQueue = new ReferenceQueue<>();
    PhantomReference ref = new PhantomReference(refObj,referenceQueue);

    三.垃圾收集算法

    1.标记-清除算法

    标记-清除算法分为两个阶段:标记、清除。首先标记所有需要回收的对象,在标记完成后回收所有被标记的对象。

    优点:算法比较简单。
    缺点:会产生大量不连续的内存碎片,而且效率不高。

    在这里插入图片描述

    2.复制算法

    这种算法会将内存划分为两个相等的块,每次只使用其中一块。当这块内存不够使用时,就将还存活的对象复制到另一块内存中,然后把这块内存一次清理掉。年轻区主要用复制算法,幸存区复制,一般都是from复制到to,谁空谁是to,适用与对象存活度较低。

    优点:效率比较高,也避免了内存碎片。
    缺点:因为另一半内存一直是空的,比较浪费空间。

    在这里插入图片描述

    3.标记-整理算法

    是标记-清除算法的升级版,也叫标记-压缩算法。在完成标记阶段后,不是直接对可回收对象进行清理,而是让存活对象向着一端移动,然后清理掉边界以外的内存。

    优点:避免了内存碎片和内存利用效率低。
    缺点:增加了一个移动的成本。

    在这里插入图片描述

    4.分代收集算法

    年轻代:存活率低-复制算法
    老年代:区域大存活率高-标记清除+标记整理算法混合实现

    四.轻GC(Minor GC)和重GC(Full GC)

    Minor GC

    当新对象去伊甸园区(Eden)申请内存失败的时候,就会进行Minor GC,对伊甸园区(Eden)回收非存活对象,而没有被回收的对象,会进入幸存区(Survivor),这种GC只发生在伊甸园区(Eden),不会影响到老年区。因为新对象分配内存大部分都在伊甸园区(Eden),所以伊甸园区(Eden)GC比较频繁。

    注意:在GC之后,还存活的对象,进入幸存区(Survivor),谁空谁是to,可以交换位置,当一个对象经历了15次GC(可以配置次数:-XX:+MaxTenuringThreshold=15),还存活,就进入老年区。

    Full GC

    清理整个堆,因为Full GC需要对整个堆进行回收,所以比Minor GC慢,因为我们要尽可能的减少Full GC的次数。我们所说的JVM调优,很大一部分就是对Full GC的优化。

    以下情况会造成 Full GC:

    • 老年区满了:年轻区的对象转入或创建大对象才会满。
    • 持久区满了(jdk7及之前版本)
    • 方法区满了(jdk8及之后版本):系统中要加载的类过多。
    • System.gc() 被显示调用
    • 通过Minor GC后进入老年代的平均大小大于老年代的可用内存:第一次Minor GC之后,有2MB的对象转入老年区,然后在下一次Minor GC的时候就会判断老年区的空间是否有2MB,如果没有就进行Full GC。
  • 相关阅读:
    二分查找算法(代码实现) [数据结构][Java]
    前端点击地图上的位置获取当前经纬度
    信息熵原理与Python实现
    机器学习知识经验分享之一:卷积神经网络介绍
    [Git入门]---gitee注册及代码提交
    大一学生HTML期末作业: 季奥林匹克运动会 8页 无js 带表单 带报告5200字
    ubuntu22.04安装公司安全VPN的方案
    python excel 读取及写入固定格式
    Linux0.11内核源码解析01
    Flask 学习-42.Flask-RESTX 快速入门
  • 原文地址:https://blog.csdn.net/twotwo22222/article/details/128183379