java gc中为什么复制算法比标记整理算法快?

为什么垃圾回收中复制算法比标记整理算法快.查了很多资料,说复制算法没有单独的mark过程,那没有单独的mark过程他是如何判断对象还活着的呢.

因为复制gc只需要把“活”的对象拷贝到survivor,还要mark什么呢?
至于怎么判断是“活”的,gc roots以下的不都是“活”的?

单纯从算法比较为什么标记整理慢呢,因为多了一次整理堆空间碎片的过程。但是两者用处不一样,抛开使用场景谈效率是不合适的。copy算法是在新生代执行的,因为新生代对象大多朝生夕灭,存活时间短,占内存小,所以一次gc后剩下的对象少而且小,直接从from survivor和eden区copy到to survivor就好了,这叫minor gc。标记整理是老年代常用的,因为老年代对象大而且生存时间长,不适合用copy算法,这叫major gc。minor gc非常频繁,所以用copy算法以较小的空间换时间是合理的。

你问mark过程如何判断对象活着,对象被gc掉同时需要满足两个条件,一个是gc roots不可达,另一个是没必要执行finalize方法。需要执行finalize方法的对象会加入到守护线程队列中执行finalize方法,一旦执行完毕依旧是gc roots不可达的话则也会被gc掉。

一个直接复制,一个打个标记

两个算法都是要解决标记清除的内存碎片问题。标记整理需要,标记完全部存活对象后,才能向一边移动。否则就不知道那些内存区域是空的。复制算法是从gc roots开始,遇到活对象就复制走了。gc roots找可达对象的过程结束就复制完了。也就是差异不在找到存活的对象,而是找完存活对象标记整理还要在来一个一个从头开始挪动存活对象,当然还要记下每个对象的大小。

我有一个疑问,标记-整理可以从头开始遍历,遇到存活的对象就移动到头的位置,遇到可以回收的对象,就回收掉,怎么感觉和标记复制算法差不多哇

我理解的是,从头开始遍历并不是从堆内存里面按顺序遍历,而是从多个GCROOT开始进行可达性遍历。这样如果遇到存活的对象就移动到头的位置,可能会覆盖掉某些GCROOT还没遍历到,但是需要存活的对象。

所以标记整理对于堆空间来说,遍历的顺序是乱序的(不是从左到右),所以还处于标记时不能乱复制移动(无法确定前面哪些位置可以覆盖),导致可能覆盖掉存活对象。等全部遍历完了,明确知道所有存活对象的位置(即标记完)时,再从左至右开始移动整理复制

你可能感兴趣的:(java gc中为什么复制算法比标记整理算法快?)