GC复制算法和标记-压缩算法的疑问

blueswind8306 2011-12-16
  之前读过毕玄的《分布式Java应用》和周志明的《深入Java虚拟机》,对于复制算法和标记-压缩算法之间的区别一直没有弄懂。我们知道Java新生代采用的是复制算法;并行GC时老生代采用的是标记-压缩算法。但既然标记压缩算法也需要移动存活对象(在压缩时),并且只用一块内存,为什么Sun还要为新生代采用复制算法呢(复制算法的坏处就是需要多占用一块内存,而且同样有内存拷贝的开销)?换句话说,复制算法的优势在哪里?
  对JVM的内部实现不清楚,所以这个问题可能很傻,还请各位大牛见谅了!
RednaxelaFX 2011-12-17
所谓的copying collector(或者叫scavenger)是空间换时间,而mark-compact则是时间换空间。

scavenger在工作的时候是不没有独立的“mark”与“copy”阶段的,而是合在一起做一个动作,就叫scavenge(或evacuate,或者就叫copy)。也就是说,每发现一个这次收集中尚未访问过的活对象就直接copy到新地方,同时设置forwarding pointer。
这样的工作方式就需要多一份空间。

mark-compact collector在工作的时候则需要分别的mark与compact阶段,mark阶段用来发现并标记所有活的对象,然后compact阶段才移动对象来达到compact的目的。如果compact方式是sliding compaction,则在mark之后就可以按顺序一个个对象“滑动”到空间的某一侧。因为已经先遍历了整个空间里的对象图,知道所有的活对象了,所以移动的时候就可以在同一个空间内而不需要多一份空间。
经典的做法叫做“LISP2” collector。可以去看看相关资料。

这样可以理解了么?空间和时间。

无论是scavenger还是mark-compact,一旦要并行化都会变复杂。要避免过多的锁竞争带来的性能瓶颈。所以很有可能会采用稍微浪费一点空间的“LAB”做法(local allocation buffer)。也可以用这个关键字搜些资料来读。

=================================================

blueswind8306 写道
我们知道Java新生代采用的是复制算法;并行GC时老生代采用的是标记-压缩算法。


这里要注意:不是“Java”采用这些实现方式,而是一个具体的JVM实现,HotSpot VM,采用了这样的实现。其它的JVM实现并不一定是这样做的。

例如说Sun的另一个JVM,稍微早期一些的,Exact VM,它的分代式GC的young gen的默认实现就是典型的使用semi-space的copying collector,只分为两部分,而不像HotSpot VM那样分为3部分(1个eden和构成semi-space的2个survivor space)。如果我收集到的信息没错的话,IBM J9里的ParallelScavenger收集器也是用这种典型semi-space设计的(而HotSpot里对应的那个叫做ParallelScavenge,很像,对吧? )。
blueswind8306 2011-12-19
明白了,多谢RednaxelaFX的耐心点拨!解释的很清楚!
Global site tag (gtag.js) - Google Analytics