垃圾回收算法
Posted SSimeng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了垃圾回收算法相关的知识,希望对你有一定的参考价值。
如何确定对象是否为垃圾?
Java中采用引用计数法和可达性分析来确定对象是否应该被回收。
- 1.引用计数法
在Java中如果要操作对象,就必须获取该对象的引用,所以可以通过引用计数法来判断该对象是否可以被回收。在给该对象添加一个引用时,引用计数加1;在为该对象减少一个引用时,引用计数减1;如果一个对象的引用计数为0,则表示该对象此时没有被引用,可以被回收。
注意:引用计数法容易产生循环引用(指两个对象相互引用,导致引用一直存在而不能被回收)的问题
Object1 Object2
| |
v v
Reference <-----> Reference
- 2.可达性分析法
可达性分析法可以解决引用计数法的循环引用问题。
具体做法:
首先定义一些GC Roots对象,然后以这些对象作为起点向下搜索,如果在GC Roots和一个对象之间没有可达路径,则称该对象是不可达的。不可达对象至少要经过两次标记才能判定其是否可以被回收。如果在两次标记后该对象仍然是不可达的,则将被垃圾收集器回收。
Java中常用的垃圾回收算法
Java中常用的垃圾回收算法有标记清、复制、标记整理和分代收集算法。
1.标记清除算法
标记清除算法是最基础的垃圾回收算法,其过程分为标记和清除两个阶段。在标记阶段标记所有需要回收的对象,在清除阶段清除可回收的对象并释放其内存空间。
注意:过程如图所示,由于标记清楚算法在清理对象所占用的内存空间后并没有重新整理可用的内存空间,因此如果内存中回收的小对象过多,则会引起内存碎片化的问题,进而引起大对象无法获得连续可用内存空间的问题。
2.复制算法
复制算法是为了解决标记清除算法内存碎片化的问题而设计的。复制算法首先将内存划分为两块大小相等的内存区域,新生成的对象都被存放到区域1中,在区域1内的对象存储满后会对区域1进行一次标记,并把标记后仍然存活的对象全部复制到区域2中,这时区域1将不存在任何存活的对象,直接清理整个区域1内的内存即可。
优缺点:复制算法的内存清理效率高且易于实现,但是可用的内存空间被压缩到原来的一半,因此存在大量的内存浪费。同时,在系统中有许多的大量长时间存活的对象,这些对象在两个区域之间来回复制会影响系统的运行效率。
3.标记整理算法
标记整理算法结合了标记清楚算法和复制算法的优点。其标记阶段和标记清除算法的标记阶段相同,在标记完成后将存活的对象移动到内存的另一端,然后清除该端的对象并释放内存。
4.分代收集算法
无论是标记清楚算法、复制算法还是标记整理算法,都无法对所有类型(长、短生命周期、大、小对象)的对象进行垃圾回收。因此针对不同对象类型,JVM采用了不同的垃圾回收算法,该算法被称为分代收集算法。
分代收集算法是根据对象的不同类型将内存划分成不同的区域,JVM将堆划分为新生代和老年代。
- 新生代主要存放新生成的对象(特点是生命周期短),每次进行垃圾回收时都有大量的对象被回收。
- 老年代主要存放大对象和生命周期长的对象,可回收的垃圾相对较少。
因此JVM根据不同类型的对象的特点进行选择不同的算法。
- 在新生代大部分采用复制算法。因为新生代每次进行垃圾回收的时候都有大量的对象 被回收,需要复制的对象少,不存在大量对象来回复制的问题。
- 老年代主要存放的是生命周期较长的对象和大对象,因此每次有少量非存活的对象需要被回收,所以使用标记清除算法。
以上是关于垃圾回收算法的主要内容,如果未能解决你的问题,请参考以下文章
JVM day02 如何判断对象可以回收垃圾回收算法分代垃圾回收垃圾回收器