Java垃圾收集器与内存分配策略

1、垃圾收集算法

1.1 分代收集

        现代的虚拟机大都采用了这种gc回收算法,通过将内存根据存活时间的不同划分为不同代,来选择最合适的对象回收算法。

  • 部分收集(Partial GC):指目标不是完整收集整个Java堆的垃圾收集,分为:

        新生代收集(Minor GC/Young GC):指目标只是新生代的垃圾收集。

        老年代收集(Major GC/Old GC):指目标只是老年代的垃圾收集。

        混合收集(Mixed GC):指目标是收集整个新生代以及部分老年代的垃圾收集。

  • 整堆收集(Full GC):收集整个Java堆和方法区的垃圾收集。

1.2 标记-清除

        首先标记出所有需要回收的对象,在标记完成后,统一回收掉所有被标记的对象,也可以反过来,标记存活的对象,统一回收所有未被标记的对象。

        缺点:a.执行效率不稳定(标记、清除两个过程的执行效率都随着对象数量增长而降低)

                   b.内存空间碎片化问题

1.3 标记-复制

        为了解决标记-清除算法面对大量可回收对象试执行效率低的问题,出现了标记-复制算法。如果内存中多数对象都是存活的,这种算法将会产生大量的内存复制开销,但对于大多数对象都是可回收的情况,算法需要复制的就是占少数的存活对象,较适合新生代。

        具体做法是把新生代分为一块较大的Eden空间和两块较小的Survivor空间,比例为8:1:1,每次分配内存只使用Eden和其中一块Survivor。发生垃圾收集时,将Eden和Survivor中仍然存活的对象 一次性复制到另外一块Survivor空间上,然后直接清理掉Eden和已经用过的那块Survivor空间。当Survivor空间不足以容纳一次Minor GC之后存活的对象时,就需要依赖其他内存区域(老年代)进行分配担保。这些对象将通过分配担保机制直接进入老年代,这对虚拟机来书就是安全的。

1.4 标记-整理

        根据老年代的特点,出现了标记-整理算法,过程与标记 - 清除算法相同,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存

2、经典垃圾收集器

经典垃圾收集器

2.1 Serial收集器

        这个收集器是一个单线程工作的收集器,但它的“单线程”的意义并不仅仅是说明它只会使用一个处理器或一条收集线程去完成垃圾收集工作,更重要的是强调在它进行垃圾收集时,必须暂停其他所有工作线程,直到它收集结束。它是HotSpot虚拟机运行在客户端模式下的默认新生代收集器,有着优于其他收集器的地方,那就是简单而高效(与其他收集器的单线程相比)。

Serial 收集器收集过程

2.2 ParNew收集器

        ParNew收集器实质上是Serial收集器的多线程并行版本,除了同时使用多条线程进行垃圾收集之外,其余的行为都与Serial收集器完全一致。除了Serial收集器外,目前只有它能与CMS收集器配合工作。

ParNew 收集器收集过程

2.3 Parallel Scavenge收集器

        Parallel Scavenge收集器是一款新生代收集器,基于标记-复制算法实现的收集器,能够并行收集的多线程收集器,目标是达到一个可控制的吞吐量(Throughput),也经常被称作“吞吐量优先收集器”。高吞吐量则可以最高效率地利用处理器资源,尽快完成程序的运算任务。

吞吐量计算公式

2.4 Serial Old收集器

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

Serial Old 收集器收集过程

2.5 Parallel Old收集器

        Parallel Old是Parallel Scavenge收集器的老年代版本,支持多线程并发收集,基于标记-整理算法实现,这个收集器是直到JDK 6时才开始提供的。在注重吞吐量或者处理器资源较为稀缺的场合,都可以优先考虑Parallel Scavenge加Parallel Old收集器这个组合。

Parallel Old 收集器收集过程

2.6 CMS收集器

        CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器,适用于互联网网站或者基于浏览器的B/S系统的服务端上。CMS收集器是基于标记-清除算法实现的,它的运作过程分为四个步骤:
1)初始标记(CMS initial mark)
2)并发标记(CMS concurrent mark)
3)重新标记(CMS remark)
4)并发清除(CMS concurrent sweep)

        其中初始标记、重新标记这两个步骤仍然需要暂停用户线程,但耗时不长。

CMS 收集器收集过程

         优点:并发收集,低停顿

         缺点:

  • CMS收集器对处理器资源非常敏感,会因为占用了一部分线程(或者说处理器的计算能力)而导致应用程序变慢,降低总吞吐量。CMS默认启动的回收线程数是(处理器核心数量+3)/4
  • CMS收集器无法处理“浮动垃圾”(Floating Garbage),有可能出现“Concurrent Mode Failure”失败进而导致另一次完全“Stop The World”的Full GC的产生。

浮动垃圾:在CMS的并发标记和并发清理阶段,用户线程是还在继续运行的,程序在运行自然就还会伴随有新的垃圾对象不断产生,但这一部分垃圾对象是出现在标记过程结束以后,CMS无法在当次收集中处理掉它们,只好留待下一次垃圾收集时再清理掉。

  • CMS是一款基于“标记-清除”算法实现的收集器,收集结束时会有大量空间碎片产生

 2.7 Garbage First收集器

        Garbage First(简称G1)收集器是垃圾收集器技术发展历史上的里程碑式的成果,它开创了收集器面向局部收集的设计思路和基于Region的内存布局形式。G1是一款主要面向服务端应用的垃圾收集器,在多 CPU 和大内存的场景下有很好的性能。HotSpot开发团队最初赋予它的期望是(在比较长期的)未来可以替换掉JDK 5中发布的CMS收集器

  • Mixed GC模式:G1可以面向堆内存任何部分来组成回收集(Collection Set,一般简称CSet)进行回收,衡量标准不再是它属于哪个分代,而是哪块内存中存放的垃圾数量最多,回收收益最大
  • Region:G1不再坚持固定大小以及固定数量的分代区域划分,而是把连续的Java堆划分为多个大小相等的独立区域(Region),每一个Region都可以根据需要,扮演新生代的Eden空间、Survivor空间,或者老年代空间。收集器能够对扮演不同角色的Region采用不同的策略去处理。
  • Region中还有一类特殊的Humongous区域,专门用来存储大对象。G1认为只要大小超过了一个Region容量一半的对象即可判定为大对象,对于那些超过了整个Region容量的超级大对象,将会被存放在N个连续的Humongous Region之中,G1的大多数行为都把Humongous Region作为老年代的一部分来进行看待
  • G1仍然保留新生代和老年代的概念,但新生代和老年代不再是固定的了,它们都是一系列区域(不需要连续)的动态集合。
  • G1收集器之所以能建立可预测的停顿时间模型,是因为它将Region作为单次回收的最小单元,即每次收集到的内存空间都是Region大小的整数倍,这样可以有计划地避免在整个Java堆中进行全区域的垃圾收集

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

  • 初始标记:仅仅只是标记一下GC Roots能直接关联到的对象,并且修改TAMS指针的值,让下一阶段用户线程并发运行时,能正确地在可用的Region中分配新对象。这个阶段需要停顿线程,但耗时很短,而且是借用进行Minor GC的时候同步完成的,所以G1收集器在这个阶段实际并没有额外的停顿
  • 并发标记:从GC Root开始对堆中对象进行可达性分析,递归扫描整个堆里的对象图,找出要回收的对象,这阶段耗时较长,但可与用户程序并发执行。当对象图扫描完成以后,还要重新处理SATB记录下的在并发时有引用变动的对象。
  • 最终标记:对用户线程做另一个短暂的暂停,用于处理并发阶段结束后仍遗留下来的最后那少量的SATB记录。
  • 筛选回收:负责更新Region的统计数据,对各个Region的回收价值和成本进行排序,根据用户所期望的停顿时间来制定回收计划,可以自由选择任意多个Region构成回收集,然后把决定回收的那一部分Region的存活对象复制到空的Region中,再清理掉整个旧Region的全部空间。这里的操作涉及存活对象的移动,是必须暂停用户线程,由多条收集器线程并行完成的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值