我是靠谱客的博主 儒雅水蜜桃,最近开发中收集的这篇文章主要介绍菜鸟学习JVM——垃圾回收算法Java垃圾回收算法,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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垃圾回收算法所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(45)

评论列表共有 0 条评论

立即
投稿
返回
顶部