浅谈Java垃圾回收机制

网友投稿 352 2022-10-25


浅谈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;

http:// }

}

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

大众说法:

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

某位前辈的理解:

选取一个对象作为GC Roots,调用其它对象去指向这个GC Roots,如果这些对象最终到达GC Roots,那表明所选取的对象不是垃圾.反之,如果对象到不了GC Roots,那么所选取的对象就是垃圾对象,就可以进行垃圾回收了.(这是一种说法);

对象指向GC Roots所形成的链条叫GC链.

至于这两种方法谁对谁错,这就要看个人的水平了.

不管怎么样,垃圾反正是产生了,那么接下来就是该怎么回收垃圾了.

二.怎么回收垃圾

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

在说垃圾回收前,先说一个题外话,我上面所说的垃圾对象,其实是指一般的对象,因为静态对象有些不同.

我经常听人说:静态方法随着类的加载而加载,随着类的消失而消失.但是,现在在我看来,这种说法是有问题的.

因为,静态对象要成为垃圾被回收,要满足三个条件:

1. 这个类的对象变成了垃圾

2. 加载这个类的类加载器变成了垃圾

3. 关于这个对象的class对象也变成了垃圾

只有满足这三个条件,静态对象才会变成垃圾被回收,要不然静态对象会一直存在于永久带中.

2.2 新生代和年老代

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

如图所示:

堆内存按1:2被划分成了年轻代(新生代)和年老代.新生代又被按照8:1:1的比例分为一个eden区和两个survivor(survivor0,survivor1)区

关于分区,我只讲到这里,有兴趣的可以自己研究.

三、垃圾回收算法

3.1 标记清除算法

如图所示:标记清除算法分成两步,第一步,标记要回收的垃圾对象,第二步就是清除被标记的垃圾对象.

同样,如图所示,标记清除算法会产生大量的内存碎片,而且效率低.所以,为了解决这个问题,出现了复制清除算法.

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

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

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

但是这个方法的缺点也很明显,那就是浪费空间.,毕竟如果按照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 标记清理算法(年老代)

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

3.4 分类算法

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

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


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:redis发布订阅功能介绍
下一篇:redis常用数据类型介绍
相关文章

 发表评论

评论列表