JVM 性能调优(三)

垃圾收集算法

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

思想: 主要分为 标记清除 两个阶段。 首先标记出所要回收的对象,标记完成后统一回收。

不足:

  1. 效率问题, 两个过程效率都不高
  2. 空间问题,标记清除后会产生大量不连续的内存碎片,碎片太多可能会导致以后程序在运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前出发一次垃圾收集动作。

复制算法(Copying)

思想: 将内存按容量划分成大小相等的两块,每次只使用一块,当这一块内存用完了,就将还存活的对象复制到另一块上,然后把已使用过的内存空间一次清理,这样是的哪次都是对整个半区进行回收,内存分配时就不用考虑内存碎片等复杂情况,只要一动堆顶指针,按顺序分配即可,
不足: 将内存缩小一半,代价高

年轻代的划分正是基于这种算法进行回收的,只不过划分不是1:1 hotspot默认Eden和Survivor比例8:1

标记-整理算法(Mark-Compact)

复制收集算法在对象存活率较高的场景下要进行较多的复制操作,效率会降低,更关键的是,如果不想浪费50%的空间,就需要额外的空间进行分配以应对被使用的内存中所有对象都100%存活的极端情况,所以老年带一般不能直接选用copying算法。

思路: 标记过程仍然和标记-清除一样,但后续步骤不是直接对可回收对象进行清理,而是让存活的对象都想一端移动,然后直接清理端边界以外的内存

分代收集算法

该算法没有什么新的思想,只是根据对象存活周期不同将内存划分为几块。一般把堆分为新生代和老年代,这样根据各个年代的特点采用适当的收集算法

年轻代 存活率低, 一般采用复制算大。
老年代,存活率高,没有额外空间可分配,就必须采用“标记-整理”/“标记-清除”

垃圾收集器

  • Serial 收集器 一个单线程的收集器 主要用于运行在Client模式下的虚拟机
    只能使用一个CPU或一条收集线程去完成收集工作,而且,在进行垃圾收集时,必须暂停其他所有工作线程,直到它收集结束
  • ParNew 收集器 是Serial收集器的多线程版本,包含Serial收集器可用的所有控制参数(-XX:SurvivorRatio/-XX:PretenureSizeThreshold等)、收集算法、对象分配规则、回收策略等都与Serial完全一样。是运行在Server模式下的虚拟机中首选的 新生代收集器 可以使用-XX:UseParNewGc来强制指定它

未完待续…

坚持原创技术分享,您的支持将鼓励我继续创作!