java垃圾收集算法、标记-清除算法、复制算法、标记-整理清除、分代收集算法


3.3.1 标记-清除算法

分为“标记”和“清除”2个阶段,先标记所有需要回收的对象,在标记完成后统一回收所有被标记的对象;

缺点:

  1. 效率,标记和清除这两个过程的效率都不高;
  2. 空间,标记和清除之后会产生大量不连续的内存碎片;

    空间碎片太多可能会导致以后再程序运行过程中需要分配较大的对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。


3.3.2 复制算法(重点)

将可用内存按容量大小大小划分为大小相等的2块(实际的JVM不是安照1:1分配),每次只使用其中1块。当这块内存用完了,就把这块内存上还活着的对象复制到另一块内存上,再把这块内存全部清除;

优点:

  1. 因为是对整个半区回收,所以内存分配时也就不用考虑内存碎片等复杂情况,只要移动堆顶指 针,按顺序分配内存即可,实现简单,运行高效。

缺点:

  1. 造成部分内存空间浪费

JAVA堆内存
https://blog.csdn.net/linsongbin1/article/details/51668859
在这里插入图片描述

  1. 将内存分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden和其中一块Survivor。 当回收时,将Eden和Survivor中还存活着的对象一次性地复制到另外一块Survivor空间上,最后清理掉Eden和刚才用过的Survivor空间。
  2. 现在的JVM把内存划分为1个较大的Eden区,2个较小的Surivior(From和To)区,HotSpot默认8:1:1;
  3. 当Survivor空间不够用时,需要依赖其他内存(这里指老年代)进行分配担保(Handle Promotion)。

新生代都是使用 复制 算法
新生代都是使用 复制 算法
新生代都是使用 复制 算法


3.3.3 标记-整理清除(重点)

复制收集算法 在对象存活率高的内存区时,效率低下,故老年代不能直接选用这种算法;

先标记所有需要回收的对象(暂时不清理),然后让所有存活的对象向一端移动,然后将端边界以外的内存全部回收;


3.3.4 分代收集算法(重点)

当前的JVM都使用分代收集算法把

JAVA堆按照对象的存活期不同分为 新生代 和老年代 ,然后根据各个年代的特点选用不同的收集算法。

  1. 在新生代 中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法;
  2. 老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记—清理”或者“标记—整理”算法来进行回收;

猜你喜欢

转载自blog.csdn.net/qq_43369986/article/details/109013499
今日推荐