文章标题

JVM垃圾回收器工作原理及使用实例介绍

垃圾收集基础

垃圾回收器常用的算法及实现原理

引用计数法(Refernce Counting)(未使用)

对于一个对象A,只要有任何一个对象引用了A,则A的引用计数就加1,当引用失效时,引用计数就减1.只要对象A的引用计数值为0,则对象A就不可能再被使用。实现时,只需为每个对象配置一个整型计数器即可。但引用计数器无法处理循环引用的情况。因此,在java垃圾回收器中没有使用这种算法。

一个简单的循环引用问题如下:有对象A和对象B,对象A包含对象B的引用,对象B包含对象A的引用。此时,对象A、B引用数都不为0。但系统中却不存在任何第3个对象引用了A或B。即A和B都应被回收,但由于相互引用而导致无法回收,致使内存泄漏。

**标记-清除算法(Mark-Sweep)

标记-清除算法将垃圾回收分为两个阶段:标记阶段和清除阶段。在标记阶段首先通过根节点,标记所有从根节点开始的较大对象。因此,未被标记的对象就是未被引用的垃圾对象。然后在清除阶段,清除所有未被标记的对象。

该算法最大的问题是存在大量的空间碎片,因为回收后的空间是不连续的。在堆空间分配过程中,尤其是对大对象的内存分配,不连续的内存空间的工作效率要低于连续的空间。

复制算法(Copying)

将现有的内存空间分为两块,每次只使用其中一块,在垃圾回收时将正在使用的内存中的存活对象复制到未被使用的内存块中,之后,清除正在使用内存块中的所有对象,交换两个内存的角色,完成垃圾回收。

若系统中垃圾数量占大多数,因此复制算法效率高。算法缺点:将系统内存折半。

java的新生代串行垃圾回收器中使用了复制算法的思想。新生代分为eden空间、from空间、to空间3部分。其中from空间和to空间可以视为用于复制的两块大小相同、地位相等,且可进行角色互换的空间块。from和to空间也称为survivor空间,即幸存者空间,用于存放未被回收的对象

在垃圾回收时,eden空间中的存活对象会被复制到未使用的survivor空间中(如to),正在使用的survivor空间(from)中的年轻对象也会被复制到to空间中(大对象,或者老年对象会直接进入老年带,如果to空间已满,则对象也会直接进入老年代)。此时,eden空间和from空间中的剩余对象就是垃圾对象,可以直接清空,to空间则存放此次回收后的存活对象。这种改进算法既保证了空间的连续性,又避免了大量的内存浪费。

标记-压缩算法(Mark-Compact)

复制算法的高效性是建立在存活对象少,垃圾对象多的前提下。这种情况在年轻代经常发生,但是在老年代更常见的情况是大部分都是存活对象,此时复制的成本将很高。

标记-压缩算法在标记-清除算法的基础上做了一些优化。首先需要从根节点开始对所有的存活对象压缩到内存的一端。之后清理边界外所有的空间。

这种方法既避免了碎片化的产生,又不需要两块相同的内存,性价比较高。

增量算法(Incremental Collecting)

在垃圾回收过程中,应用程序的所有线程都会挂起,暂停一切正常工作,等待垃圾回收的完成。如果垃圾回收时间过长,应用程序就被挂起很久,影响用户体验或系统的稳定性。

增量算法的基本思想是,如果一次性将所有的垃圾进行处理,需要造成系统长时间停顿,那么就让垃圾收集线程和应用程序线程交替执行。每次,垃圾收集线程只收集一小片内存空间,接着切换到应用程序线程。以此反复,直到垃圾收集完成。

优点:减少系统停顿时间 缺点:因为线程切换上下文转换的消耗,会使垃圾回收的总体成本上升,造成吞吐量的下降。

分代(Generational Collecting)

不同阶段最优的方式就是使用合适的算法用于本阶段的垃圾回收,分代算法就是基于这种思想。它将内存区间根据对象特点分成几块,再根据每块内存区间的特点,使用不同的回收算法,以提高效率。

以HotSpot虚拟机为例,它将所有的新建对象都放入年轻代的内存区域,年轻代的特点是对象会很快回收,因此,在年轻代就选择效率较高的复制算法。当一个对象经过几次回收后依然存活,对象会被放入老生代的内存空间。在老生代中的对象被认为将是常驻内存的,使用标记-压缩算法,以提高回收效率。

从不同的角度分析垃圾收集器,可以将其分为不同的类型

  1. 按线程数分,可以分为串行垃圾回收器和并行垃圾回收器。在并行能力强的cpu上,使用并行回收器可以缩短GC的停顿时间。
  2. 按照工作模式分,可分为并发式垃圾回收器和独占式垃圾回收器。并发式垃圾回收器和应用程序交替工作;独占式垃圾回收器一旦运行,就停止应用程序中的其它线程。
  3. 按碎片处理方式,可分为压缩式和非压缩式。压缩式,对存活对象进行压缩整理,消除回收的碎片
  4. 按工作的内存区间,分为新生代和老年代

可用以下指标评价一个垃圾处理器

  • 吞吐量:在应用程序的生命周期内,应用程序所花费的时间和系统总运行时间的比值。系统总运行时间=应用程序+GC耗时。
  • 垃圾回收器负载:和吞吐量相反,垃圾回收负载指回收耗时与系统运行总时间的比值
  • 停顿时间:指垃圾回收器运行时,应用程序的暂停时间。对于独占式,停顿时间较长;对于并发式时间较短,效率可能不如独占式,故系统吞吐量可能会低
  • 垃圾回收频率:指多长时间会运行一次垃圾回收器。一般,对固定的应用,频率越低越好。通常增带堆空间可以有效的降低垃圾回收发生的频率,但有可能增加回收的产生的停顿时间。
  • 反应时间:指当一个对象被称为垃圾后多长时间内它所占据的内存空间会被释放。
  • 堆分配:一个良好的垃圾收集器应该有一个合理的堆内存区间划分。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值