• JVM垃圾回收之JVM GC算法探究


    JVM垃圾回收之JVM GC算法探究

    Java虚拟机(JVM)中,垃圾回收(Garbage Collection,GC)是自动管理内存的重要机制,它负责回收程序中不再使用的对象所占用的内存。GC算法是垃圾回收的核心,下面我们将详细介绍四种常见的GC算法,并通过代码示例进行简单的分析。

    1. 标记清除算法(Mark-Sweep)

    标记清除算法是最基础的GC算法之一。它分为两个阶段:标记阶段和清除阶段。在标记阶段,GC遍历所有对象,找出并标记不再使用的对象(即需要被回收的对象)。在清除阶段,GC将标记过的对象所占用的内存进行释放。

    优点:实现简单,内存回收较为彻底。

    缺点:标记和清除两个阶段的效率都不高,尤其是标记阶段,需要遍历所有对象。并且,由于标记和清除的时机不同步,可能会导致内存碎片化,需要额外的空间进行内存整理。

    以下是标记清除算法的Java代码示例:

    public class MarkSweepExample {
        public static void main(String[] args) {
            Object[] array = new Object[10];
            for (int i = 0; i < array.length; i++) {
                array[i] = new Object();
            }
            // 执行标记清除算法
            sweep();
        }
        
        private static void sweep() {
            for (Object obj : array) {
                if (obj != null) {
                    System.out.println("Marking " + obj);
                }
            }
            array = null; // 执行清除阶段
            System.gc(); // 提示JVM进行垃圾回收
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    1. 标记整理算法(Mark-Compact)

    标记整理算法是对标记清除算法的改进,它在清除阶段将标记过的对象进行内存整理,避免内存碎片化。

    优点:解决了内存碎片化问题。

    缺点:由于需要整理内存,增加了GC的耗时。并且,当对象在堆中分布不均时,可能需要较大的空间进行内存整理。

    以下是标记整理算法的Java代码示例:

    public class MarkCompactExample {
        public static void main(String[] args) {
            Object[] array = new Object[10];
            for (int i = 0; i < array.length; i++) {
                array[i] = new Object();
            }
            // 执行标记整理算法
            compact();
        }
        
        private static void compact() {
            for (Object obj : array) {
                if (obj != null) {
                    System.out.println("Marking " + obj);
                } else {
                    System.out.println("Compact " + obj);
                }
            }
            array = null; // 执行整理阶段
            System.gc(); // 提示JVM进行垃圾回收
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    1. 复制算法(Copying)

    复制算法将堆内存分为两个区域,一部分为使用区,另一部分为垃圾区。每次GC时,将正在使用的对象复制到垃圾区,然后将使用区的内存清空。

    优点:可以充分利用堆内存空间,避免了内存整理的开销。并且,由于只有正在使用的对象需要复制,所以GC的耗时相对较短。

    缺点:需要额外的内存空间来存放正在使用的对象,当堆内存中存活的对象较多时,可能会占用较大的空间。此外,由于需要复制对象,可能会对程序的性能产生影响。

    1. GC Roots 定位算法

    GC Roots 定位算法是垃圾回收中另一个重要的概念。在 JVM 中,一些对象可能被 GC 无法直接找到的引用所引用,这些对象被称为 GC Root。GC Roots 定位算法就是用来找到这些 GC Root 的。

    一般来说,GC Roots 定位算法主要关注以下几个方面:

    • 栈:线程的栈是 GC Root 的重要来源,栈中的对象可能会被其他对象引用。
    • JNI 引用:JNI(Java Native Interface)是 Java 平台的一种机制,允许 Java 代码与本地代码进行交互。在 JNI 代码中创建的对象可能会被 Java 对象引用,因此这些对象需要被标记为 GC Root。
    • CPU 寄存器:CPU 寄存器中的对象可能会被其他对象引用,因此需要将寄存器中的对象标记为 GC Root。
    • 全局变量:全局变量是 Java 对象在 Java 代码中的一种常见引用方式,因此全局变量中的对象需要被标记为 GC Root。

    总的来说,GC Roots 定位算法的目标是找到所有的 GC Root,以便于垃圾回收器能够正确地回收不再使用的对象。

    总结

    JVM 的垃圾回收机制是 JVM 自动内存管理的重要组成部分,它能够有效地回收不再使用的对象,避免内存泄漏和内存溢出等问题。而垃圾回收机制的核心就是 GC 算法和 GC Roots 定位算法。了解和掌握这些算法的原理和机制有助于我们更好地理解和使用 JVM。

  • 相关阅读:
    【Vue3响应式原理#02】Proxy and Reflect
    阿里P8MySQL,基础/索引/锁/日志/调优都不误,一锅深扒端给你
    小程序搜索词排名优化的诀窍
    STP学习的第一篇
    JAVA排序
    虚拟化逻辑架构: 创建KVM中的VM与实现VNC远程登录
    微信小程序线上加载使用iconfont问题
    查找算法之二分查找
    jeecgboot-前端组件封装代码示例
    反射机制(Reflection)
  • 原文地址:https://blog.csdn.net/a1774381324/article/details/133691361