JAVA垃圾回收机制及垃圾回收器

目录

1. 什么是垃圾回收机制

 2. 如何判断对象可回收

2.1 引用计数法

2.2 可达性分析算法

3.垃圾回收算法

3.1 标记-清除算法

3.2 标记-整理算法

3.3 复制算法

4 分代回收策略

5.垃圾回收器

5.1 Serial

5.2 ParNew

5.3 Parallel Scavenge

5.4 Serial Old

5.5 Parallel Old收集器

5.6 CMS

5.7 G1



1. 什么是垃圾回收机制

垃圾回收(Garbage Collection,GC)就是将JVM内存中长期未使用的或者已经死亡的对象清除,释放占用的内存空间,防止内存泄露。

 2. 如何判断对象可回收

即如何判断一个对象是否是垃圾对象,有两种方式:引用计数法和可达性分析算法。

2.1 引用计数法

引用计数算法(Reachability Counting)是通过在对象头分配一块内存区域存放对象被引用的次数;如果该对象被其他对象引用,则次数加1,如果删除该对象的引用,则次数减1,当该对象的引用次数为0时,那么该对象就可以被回收。

但引用计数算法有个缺点,就是无法解决对象之间的循环引用问题 所以就有了可达性分析算法来解决这个问题。

2.2 可达性分析算法

通过GC Roots对象作为搜索起点,搜索走过的路径称为引用链,通过引用链判断对象是否有到达GC Roots的路径来判断对象是否可回收,如果不可达可判断该对象为垃圾对象。 

 tips:什么是GC Roots

可作为GC Roots的对象有以下四种:

  • 虚拟机栈中引用的对象
  • 本地方法栈中引用的对象
  • 方法区中类的静态属性引用的对象
  • 方法区中常量引用的对象

3.垃圾回收算法

第二节谈论的是如何判断对象为垃圾,这一节谈论的是如何进行垃圾回收,垃圾回收算法主要有:标记-清除算法、标记-整理算法、复制算法

3.1 标记-清除算法

标记-清除算法就是对可回收的对象进行标记,然后垃圾回收的线程直接释放被标记的内存。

缺点:容易产生大量的内存碎片

3.2 标记-整理算法

标记-整理算法的做法是先将可回收的对象进行标记,然后将未标记的对象(即存活的对象)移动到内存的一端,然后将剩余的区域的对象清除。

标记-整理算法就解决了标记-清除算法产生大量内存碎片的问题,但也有缺点:频繁移动导致效率低下。 

3.3 复制算法

复制算法将内存按容量划分成大小相等的两块,每次只是用其中的一块,当这一块的内存使用完了,就将还存活的对象复制到另一半内存上,然后再把已使用过的那一半内存全部清空。

 复制算法不会产生内存碎片,效率也比标记-整理算法高,但每次只使用一半的内存,代价太高

既然三种垃圾回收算法都各自有优缺点,那还有没有其他更完美的算法,答案是没有啦。但聪明的工程师们将三种垃圾回收算法与jvm内存结合起来,实现利益最大化。

4 分代回收策略

Java 堆(Java Heap)是JVM所管理的内存中最大的一块,堆又是垃圾收集器管理的主要区域,先来看看jvm 堆的内存结构:

 Java 堆主要分为2个区域-年轻代老年代,其中年轻代又分 Eden 区Survivor 区,其中 Survivor 区又分 FromTo 2个区。

Eden区:大多数情况下,对象会在新生代Eden区中分配。当Eden区没有足够空间进行分配时,虚拟机会发起一次 Minor GC。Minor GC相比Major GC更频繁,回收速度也更快。通过Minor GC之后,Eden区中绝大部分对象会被回收,而那些存活对象,将会送到Survivor的From区(若From区空间不够,则直接进入Old区)

Survivor区:Survivor区相当于是Eden区和Old区的一个缓冲,每次执行Minor GC,会将Eden区中存活的对象放到Survivor的From区,而在From区中,仍存活的对象会根据他们的年龄值来决定去向。(From SurvivorTo Survivor的逻辑关系会发生颠倒: From变To , To变From,目的是保证有连续的空间存放对方,避免碎片化的发生)

 分代回收策略就是:

  • 在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。

  • 在老年代中,因为对象存活率高、没有额外空间对它进行分配担保,就必须使用标记-清理算法或者标记-整理算法来进行回收。

5.垃圾回收器

上图展示了7种用于不同分代的收集器,如两个收集器之间存在连线,就说明他们可以搭配使用,收集器所处的区域则表示它是属于新生代收集器还是老年代收集器。

5.1 Serial

Serial收集器是最基础、最悠久的收集器,基于标记-复制算法,用于新生代垃圾回收。

Serial是一个单线程工作的收集器,在它进行垃圾收集时,必须暂停其他所有工作线程,直到它收集结束。

Serial的优点是简单而高效,对于内存受限的环境,他是所有收集器里额外内存消耗最小的,对于单核处理器或者核心处理器较少的环境来说,Serial由于没有线程交互的开销,专心做垃圾回收自然可以获得最高的单线程收集效率。

Serila适用于运行在客户端模式下的虚拟机。

5.2 ParNew

ParNew实际上就是Serial收集器的多线程并行版本,同样是基于标记-复制算法,用于新生代垃圾回收。

ParNew收集器在单核心处理器的环境中收集效果不如Serial。

ParNew默认开启收集线程数与处理器核心数量相同,随着被使用的处理器核心数量的增加,ParNew对于垃圾收集时系统资源的高效利用还是很有好处的。

5.3 Parallel Scavenge

Parallel Scavenge收集器也是一款新生代收集器,同样是基于标记-复制算法,也是能够并行收集的多线程收集器。

Parallel Scavenge收集器的特点是它的关注点与其他收集器的不同,CMS的关注点是尽可能地缩短垃圾收集时用户停顿的时间,而Parallel Scavenge收集器的目标则是达到一个可控制的吞吐量,Parallel Scavenge收集器也被称作“吞吐量优先收集器”。

Parallel Scavenge收集器提供了两个参数用于精确控制吞吐量,分别是控制最大垃圾收集停顿时间的-XX:MaxGCPauseMills,以及直接设置吞吐量大小的-XX:GCTimeRatio参数。

另外,Parallel Scavenge也提供了一个参数-XX:+UseAdaptiveSizePolicy,当这个参数开启后,就不需要人工制定新生代的大小(-Xmn)、Eden与Survivor区的比例(-XX:SurvivorRatio)、晋升老年代对象大小(-XX:PretenureSizeThreshold)等参数细节了,虚拟机会根据当前系统的运行情况手机性能监控信息,动态调整这些参数以提供最适合的停顿时间或最大的吞吐量。这种调节方式被称为垃圾收集的自适应的调节策略。

5.4 Serial Old

Serial Old是Serial收集器的老年代版本,它同样是一个单线程收集器,使用标记-整理算法

5.5 Parallel Old收集器

Parallel Old是Parallel Scavenge收集器的老年代版本,支持多线程并发收集,基于标记-整理算法实现,这个收集器是知道JDK 6才开始提供。

5.6 CMS

CMS(Concunrrent Mark Sweep)收集器是一种以获得最短回收停顿时间为目标的收集器,用于老年代垃圾回收,基于标记-清除算法实现。

整个过程分为四个步骤:

(1)初始标记;

(2)并发标记;

(3)重新标记;

(4)并发清除。

CMS是一款优秀的收集器,他最主要的优点在名字上已经体现出来:并发收集、低停顿

CMS至少有以下三个明显的缺点:

(1)CMS收集器对处理器资源非常敏感;

(2)CMS无法处理“浮动垃圾”,有可能出现“Concurrent Mode Failure"失败进而导致另一次完全“Stop The Word"的Full Gc的产生。

(3)CMS采用标记-清除算法,这意味着收集结束时会有大量空间碎片的产生。

5.7 G1

Garbage First(G1)开创了收集器面向局部收集的设计思路和基于Region的内存布局形式。它可以面向对内存任何部分来组成回收集(Collection Set)进行回收,衡量的标准不再是它属于哪个分代,而是哪块内存中存放的垃圾数量最多,回收收益最大,这就是G1收集器的Mixed GC模式。

G1把连续的Java堆划分为多个大小相等的独立区域(Region),每一个Region都可以根据需要,扮演新生代的Eden空间、Surivior空间,或者老年代空间。收集器能够对扮演不同角色的Region采用不同的策略去处理。支持用户指定期望的停顿时间

G1收集器的运作过程大致可分为以下四个步骤:

(1)初始标记;

(2)并发标记;

(3)最终标记;

(4)筛选回收。

G1从整体来看是基于“标记-整理”算法,但从局部(两个Region之间)上看又是基于“标记-复制”算法实现,故与CMS采用标记-清理算法不同的是,G1不会产生空间碎片。

但G1无论是为了垃圾收集产生的内存占用,还是程序运行时的额外执行负载都要比CMS要高。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

pandamig

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值