概述
Java垃圾回收算法
所有的垃圾回收算法都是为了解决三个问题:
- 哪些内存需要回收
- 什么时候回收
- 怎么回收
引用计数法(Reference Counting)
引用计数法原理很简单,给每个对象分配一个计数器,当被引用时就加一,引用失效就减一。计数器为零时,则说明该对象不可能再被使用。引用计数法效率不错,大部分情况下是个不错的算法,但它有一个非常明显的缺点,就是无法回收互相引用的对象,从而引起内存泄露。这也是主流Java虚拟机没有选择它的一个重要因素。
上图中很明显A和B已经不其他对象引用了,但他们互相引用,彼此的计数器都不为零,用引用计数法无法将其回收,从而造成了内存泄露。
标记-清除法(Mark-Sweep)
标记-清除算法是现代垃圾回收算法的思想基础,后面提到的所有算法都是基于该算法的思想。从名字就能看出,该算法分两个阶段进行——“标记”和“清除”。首先通过根对象标记所有可达的对象,然后清除所有未被标记的不可达对象。该算法有一个比较大的缺点,就是容易产生内存碎片。过多的内存碎片对于大对象的内存分配,效率非常低。回收过程如下图:
回收前
白色表示空闲,灰色表示存活对象,黑色表示垃圾对象
回收后
什么是可达?
简单的说,就是如果能通过一条路径找到该对象,那么就将该对象称为可达对象。
专业点的说法就是,通过一系列根对象(GC Roots)作为起点,向下搜索,搜索所有的引用路径——引用链(Reference Chain),只要根对象和该对象相连,那么该对象就为可达对象,反之,则为不可达的对象,则证明此对象是不可用的,需要被回收。
复制算法(Copying)
复制算法基于标记-清除算法并对其产生过多内存碎片的缺点进行了优化。复制算法将内存空间分成两等份(如下图的A和B),每次只使用其中的一块,当垃圾回收的时候,将A中的可达对象复制到B中,然后清空A中的所有对象。这样就避免了产生内存碎片的情况,但这种算法的缺点也是显而易见的,那就是太浪费空间。
A
B
标记-压缩法(Mark-Compact)
光从名字上就能看出,该算法继承自标记-清除算法。该算法在标记和清除之间又加了一个操作——压缩。首先将标记所有可达对象,然后将所有可达对象压缩(或者叫移动)到内存的一端,最后将边界以外的空间全部清空。这样既避免了产生内存碎片,又不需要空出一块内存空间,一举两得。
回收前
回收后
跟上面不同的是:这是同一块内存回收前和回收后的不同状态,而上面是A、B两块不同的内存。
总结(Summary)
JVM中采用的并不是某一种回收算法,而是多种算法组合使用,因为任何一种算法都不是完美的,都有自身的优缺点,有自己适用的场景。需要把他们放到合适的地方,这样才能各尽其能,达到一个最好的效果。
最后
以上就是儒雅水蜜桃为你收集整理的菜鸟学习JVM——垃圾回收算法Java垃圾回收算法的全部内容,希望文章能够帮你解决菜鸟学习JVM——垃圾回收算法Java垃圾回收算法所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复