欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

浅谈Java垃圾回收机制

程序员文章站 2022-06-18 10:28:59
一.什么是垃圾java中,什么样的对象是垃圾?有人说:没有被引用的对象就是垃圾对象.我一开始对此也是深信不疑的,但是当年我这么回答面试官的时候,得到的是一个大大的白眼.判断一个对象是否是垃圾,...

一.什么是垃圾

java中,什么样的对象是垃圾?有人说:没有被引用的对象就是垃圾对象.我一开始对此也是深信不疑的,但是当年我这么回答面试官的时候,得到的是一个大大的白眼.

判断一个对象是否是垃圾,有两种算法,一种是引用计数法,但是,这种方法解决不了循环引用的问题.

/**循环问题*/
public class demo{
    public demo instance;
    public static void main(string[] args) {
        demo a=new demo();
        demo b=new demo();
        a.instance=b;
        b.instance=a;
        a=null;
        b=null;
    }
}

浅谈Java垃圾回收机制

另外一种方法,可以解决这种循环引用问题,那就是可达算法.关于可达算法,就我目前所知道的,有两种解释:

大众说法:
通过一系列的称谓“gc roots”的对象作为起始点,从这些节点开始向下搜索,搜索所有走过的路径为引用链,当一个对象到gc roots没有任何引用链项链时,则证明此对象时不可用的.

浅谈Java垃圾回收机制 

某位前辈的理解:
选取一个对象作为gc roots,调用其它对象去指向这个gc roots,如果这些对象最终到达gc roots,那表明所选取的对象不是垃圾.反之,如果对象到不了gc roots,那么所选取的对象就是垃圾对象,就可以进行垃圾回收了.(这是一种说法);
对象指向gc roots所形成的链条叫gc链.

浅谈Java垃圾回收机制 

至于这两种方法谁对谁错,这就要看个人的水平了.
不管怎么样,垃圾反正是产生了,那么接下来就是该怎么回收垃圾了.

二.怎么回收垃圾

2.1 静态对象什么时候变成垃圾被回收

在说垃圾回收前,先说一个题外话,我上面所说的垃圾对象,其实是指一般的对象,因为静态对象有些不同.
我经常听人说:静态方法随着类的加载而加载,随着类的消失而消失.但是,现在在我看来,这种说法是有问题的.
因为,静态对象要成为垃圾被回收,要满足三个条件:

1. 这个类的对象变成了垃圾
2. 加载这个类的类加载器变成了垃圾
3. 关于这个对象的class对象也变成了垃圾
只有满足这三个条件,静态对象才会变成垃圾被回收,要不然静态对象会一直存在于永久带中.

2.2 新生代和年老代

既然要说垃圾回收,那么我们就先来看看跟垃圾回收密切相关的堆内存(新生代和年老代)

浅谈Java垃圾回收机制
浅谈Java垃圾回收机制 

如图所示:
堆内存按1:2被划分成了年轻代(新生代)和年老代.新生代又被按照8:1:1的比例分为一个eden区和两个survivor(survivor0,survivor1)区
关于分区,我只讲到这里,有兴趣的可以自己研究.

三、垃圾回收算法

3.1 标记清除算法

浅谈Java垃圾回收机制
浅谈Java垃圾回收机制
浅谈Java垃圾回收机制 

如图所示:标记清除算法分成两步,第一步,标记要回收的垃圾对象,第二步就是清除被标记的垃圾对象.
同样,如图所示,标记清除算法会产生大量的内存碎片,而且效率低.所以,为了解决这个问题,出现了复制清除算法.

3.2 复制清除算法(专门用于处理年轻代垃圾的)

浅谈Java垃圾回收机制
浅谈Java垃圾回收机制
浅谈Java垃圾回收机制 

如图所示,所谓复制清除算法,就是在要进行垃圾回收的时候,先将活着的对象整齐的复制到一块空闲区域,然后再将原来的区域的垃圾全部清除.

复制清除算法的优点:效率高于标记清除算法,活着的对象是整齐排列的,没有内存碎片.

但是这个方法的缺点也很明显,那就是浪费空间.,毕竟如果按照1:1比例来划分空间的话,那么将会有50%的空间被浪费.不过,在jvm中,年轻代空间并不是按照1:1来划分的,而是按照8:1:1的比例分为一个eden区和两个survivor(survivor0,survivor1)区。一个eden区,两个 survivor区(一般而言)。大部分对象在eden区中生成。回收时先将eden区存活对象复制到一个survivor0区,然后清空eden区,当这个survivor0区也存放满了时,则将eden区和survivor0区存活对象复制到另一个survivor1区,然后清空eden和这个survivor0区,此时survivor0区是空的,然后将survivor0区和survivor1区交换,即保持survivor1区为空,这样的过程也被叫做minor gc,每进行minor gc一次,存活着的对象的年龄就会加1,当存活着的对象的年龄到达15岁时,就会被送进年老代.
当然,当整个当survivor1区不足以存放 eden和survivor0的存活对象时,也会将存活对象直接存放到年老代。若是年老代也满了就会触发一次full gc,也就是新生代、老年代都进行回收

3.3 标记清理算法(年老代)

浅谈Java垃圾回收机制 

将活着的对象一个接一个的按顺序排好,然后再清除变成垃圾的对象.这种方法不会造成碎片,也不会造成内存的浪费.但是效率不高.所以,这种方法不适合在年轻代使用,而是在对象生命力很顽强的年老代使用

3.4 分类算法

所谓分类算法,就是根据内存的不同,采用不同的垃圾回收方式(上面的1,2,3)进行垃圾回收.

暂时就先说到这里,因为再说下去,还会有什么gc停顿以及垃圾收集器等.如果大家想要了解更多的垃圾回收的知识,可以看类似<<深入理解java虚拟机:jvm高级特性与最佳实践>>等书籍.毕竟这些书是我的一位前辈推荐给我的.

浅谈Java垃圾回收机制

到此这篇关于浅谈java垃圾回收机制的文章就介绍到这了,更多相关java垃圾回收内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

相关标签: Java 垃圾回收