Java 垃圾回收算法

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

目录

前言

一、垃圾的确定

二、回收算法

1.标记清除算法

2.标记整理算法

3.复制算法

4.分代收集算法

总结


前言

JVM的垃圾回收机制帮助java程序员管理内存,提高了开发效率,而理解垃圾回收机制可以帮助我们提高代码质量,提升自己的硬实力。

一、垃圾的确定

既然我们要回收垃圾,那么jvm是怎么判断一个对象是否属于可回收的对象呢?

答案显然:如果一个对象将来不会被使用,那也没有存在的必要了

确定垃圾的常见方法有以下两种:

  1. 引用计数法:在 *java*中,要操作一个对象都是通过引用来实现的,因此我们可以通过该对象的引用次数来判断对象是否可回收。但是这样会引出一个问题,我们看下面的代码:
    public class Main {
        static class Person {
            private Person friend;
            
            public void setFriend(Person friend) {
                this.friend = friend;
            }
        }
    
        public static void main(String[] args) {
            Person person1 = new Person();
            Person person2 = new Person();
    
            person1.setFriend(person2);
            person2.setFriend(person1);
    
            // 此时person1和person2相互引用,导致循环引用
        }
    }
    
     如此,person1和person2对象将不能被回收,这就是引用计数法在循环引用问题上的缺陷。如果有大量的循环引用将会导致内存泄漏问题。
  2. 可达性分析:从根节点GC root 出发,不断向下搜索,如果一个对象不能通过该根节点遍历到,说明这是一个可回收对象,即不可达。但是java不会立即回收该对象,而是经过两次该操作如果发现仍不可达,则回收。

二、回收算法

1.标记清除算法

该算法顾名思义,首先遍历内存空间,标记需要回收的对象,然后清除这些对象。但是这样做会导致一些问题:

回收前:

Java 垃圾回收算法_第1张图片

回收后:

Java 垃圾回收算法_第2张图片

我们发现,通过该算法回收后会有大量的碎片空间,此时如果有一个占用内存比较大的对象,这些碎片化的空间该如何存放?

为了应对此问题,于是有了下面这种算法:

2.标记整理算法

该算法在标记完成之后不是立即回收被标记对象,而是将存活对象都移至一个角落,这样剩余的可用空间就是一个连续的空间了。

Java 垃圾回收算法_第3张图片

3.复制算法

将内存划分为两个部分(区域一和区域二),所有存活的对象每次都只会存在一个区域内。

假设此时创建了一批对象,将他们都存放到区域一内,经过一段时间后,垃圾回收器对该区域进行垃圾回收,此时存活下来的对象都移至区域二,如此反复进行。

为什么要这么做呢?我们发现标记整理算法在对存活对象进行移动时比较耗费资源,因此我们直接采用整体复制的方法减少开销。

但是复制算法有一个缺陷,那就是每次的可用空间只有原来的一半了。

4.分代收集算法

目前大部分JVM采用当前算法,核心思想是根据每一块内存区域的特点使用不同的垃圾回收算法,实现效率的最大化。

众所周知,java对象都是存放在堆内存中,而堆内存又划分为新生代和老年代(空间比例大概1:3)。

刚开始创建的对象都会被放入新生代(大对象除外),经过多次垃圾回收,每次回收年龄+1,如果存活年龄大于15,则进入老年代,老年代区一般不会进行垃圾回收(除非内存实在是不够了,快要出现OOM了)。

新生代采用的是复制算法:

新生代又分为 一个Eden区和两个Survivor区。总有一个Survivor区处于空闲状态(都是可用空间),每次进行垃圾扫描,存活下来的对象都会被移至 空闲的Survivor区域。

在Java中,老年代通常使用标记-清除(Mark-Sweep)算法和标记-压缩(Mark-Compact)算法来回收垃圾。这两种算法通常会结合使用,具体的回收策略还取决于具体的垃圾收集器。标记-清除算法会先标记出所有需要回收的对象,然后再清除这些对象,但这可能会导致内存碎片问题。标记-压缩算法则会在清除对象之后,将存活的对象向一端移动,从而减少内存碎片化。


总结

总的来说,Java的垃圾回收算法经过不断的优化和改进,采用了多种算法相结合的方式,以提高回收效率和减少内存碎片。分代回收算法是其中比较重要的一种,能够有效提升垃圾回收的效率。

你可能感兴趣的:(算法,java,垃圾回收算法)