0%

虚拟机小结

Increased knowledge will help you now. Have mate’s phone bugged.

基于垃圾回收(GC)的相关算法

1.引用计数 (Reference Counting)

1
2
3
4
5
6
  这是一种最简单的垃圾回收算法,通过对一个对象的引用计数,新增一个引用计数器+1,减少一个引用计数器-1.
若引用计数器为0则对象无法使用且可被清除
优点:每个对象只需要维护一个计数器即可
缺点:无法解决循环引用的问题(即,两个对象互相引用对方即使不需要这两个对象也无法清除导致OOM)

注:Java的虚拟机并未使用这种算法

2.标记-清除(Mark-Sweep)

1
2
3
4
  这种算法的思路是:将垃圾回收分为两个部分,先标记即通过GC Root来标记所有从该根节点引用的对象,然后
清除过程,将所有未被标记的对象清除
优点:解决了循环引用的问题
缺点:因为清除过程是直接将未标记对象清除导致出现大量内存碎片在对大对象分配内存时尤为严重

3.复制(Copying)

1
2
3
4
5
6
7
8
9
10
11
  这种算法将内存分为两部分,每次只对其中一块分配内存。当进行垃圾回收时,同样先通过GC Root来标记所有从
该根节点引用的对象,但清除过程是将所有标记得对象放入另一块内存,然后清除所有未被标记的对象。
优点:解决了内存碎片的问题。
缺点:直接将内存分为两部分,每次只能使用一般内存,大大降低了内存的使用率

在上面的算法基础上,Java的新生代串行垃圾回收器优化了该算法,即:将内存分为三个部分,分别为Eden空间,
两块survivor空间(分别为from空间和to空间),进行垃圾回收时,所有对象都先存于eden和一块survivor空间,
然后同上进行标记工作,将所有标记了的对象存于另一块survivor空间,接着就是清除所有未被标记的空间。两块
survivor空间不断的循环使用。适用于存活对象少,垃圾对象多的情况
注: 往往eden空间比survivor空间大上不少(HotSpot默认为8:1),因为新生代的对象存活率很低,这样可以提高
内存的使用率也确保了内存的连续性

4.标记-压缩(Mark-Compact)

1
2
3
这种算法在标记-清除算法的基础上,改进了清除过程,不同于直接的清除而是先将所有存活(即被标记)的对象压缩到
内存的一端,然后在对此边界外边的所有对象全部清除
优点: 解决了内存碎片的问题且不需要对内存进行分割使用,适用于存活对象多的情况

5.增量算法(Incremental Collecting)

1
2
3
4
5
6
  该算法是为了解决当进行GC过程时,系统CPU的占用率很高。因此应用程序的所有线程都会挂起,等待GC完成。但这样
会对用户造成很差的体验并且影响系统的稳定性。
增量算法是将垃圾回收线程与应用程序线程交替执行,垃圾回收线程只进行一部分内存的回收然后切换到应用程序的线程,
依次反复,直到完成GC过程
优点: 提高了应用程序的响应程度
缺点: 由于会进行很多的线程切换和上下文切换,所有总体来看会降低系统的吞吐量

6.分代算法(Generational Collecting)

1
2
3
4
5
  分代算法的思想是根据不同的内存对象进行不同的垃圾回收策略。即将内存空间根据对象的特点分为不同的空间,使用不同
的垃圾回收算法,来提高垃圾回收的效率。
比如HotSpot先将所有的新建对象放入新生代,其特点是存活率低,因此可使用效率较高的复制算法。当新生代的对象年龄的
增长(每一次GC完毕,存活的对象年龄+1)到一定数量时,就会被放入老生代。在老生代里的对象都经历过多次GC,所有对象的
存活率都很高,因此采用标记-压缩算法效率更高。

by Jedrek