垃圾回收是做什么的?

1 分配内存  

2 保证引用的对象留在内存中,不被回收

3 回收那些执行中的代码无法引用到的内存(ps:两个对象的相互引用,但没有任何代码引用他们,这时这两个对象应该被回收)


基本术语:

对象被引用叫做活着(live),不在被引用的对象(dead),术语叫做垃圾(garbage)。发现和释放(叫做回收(reclaiming))这些垃圾占用的空间叫做垃圾收集。

通常整个heap或heap的一部分被填满或者达到某个值的时候会出发垃圾收集

对于动态的内存分配算法,主要的问题就是需要在保持内存分配回收效率的同时避免内存碎片


安全性:使用中的数据永远不能被错误释放

有效性:在很少的周期内垃圾就应该被回收


垃圾回收的时候会暂停,暂停的时候应用系统是不能运行的。这时就需要在回收的时间,用到的空间,回收的频率之间做出权衡。for example :堆很小的时候垃圾收的频率应该会快,相反,当堆很大的时候,其填满需要的时间会变长,所以对应的手机频率应该减慢。


内存碎片:当垃圾对象内存释放后,会在内存空间形成小块的空隙,这种情况会导致没有一个足够大的连续区域来分配给一个较大的对象。有一种应对这种内存碎片的做法就是压缩。



设计垃圾回收需要作出的一系列决策:

1 串行还是并行?(  Serial  or  parallel

     在串行中,同一时间只能做一件事情,即便有多个cpu也只能有一个进行垃圾回收。当使用并行的时候,会在不同的cpu上同时执行,速度更快,但是其设计起来比较复杂,还容易产生内存碎片。

2 并发的还是停止一切(Concurrent or Stop the world

     Stop the world 是在垃圾回收的时候程序将完全暂停,Concurrent是在垃圾回收的时候应用程序可以同时的执行,但还是会有短暂的暂停。Stop the world 设计起来简单,Concurrent设计复杂,要格外小心。因为当做垃圾回收的时候堆没有冻结,要小心不要改变对象的状态

3 压缩还是不压缩还是拷贝 (compaction or  copy)

     压缩的意思就是把所有live的对象放到一堆,让对象很容易进入到内存中,非压缩就是在原地将dead的对象回收掉,这样虽然说速度很快但是容易产生大量的内存碎片。拷贝是将对象复制到另外一个地方,这样的好处是原来内存可以直接为空,简单快速,但是缺点是需要额外的存储空间。


性能度量(指标):

1 吞吐量:在长周期里出去花费在垃圾收集上的时间占总时间的百分比。

2 垃圾收集开销:垃圾收集占总时间点百分比。

3 暂停时间:系统在垃圾回收的时候暂停的时间。

4 收集频率:发生垃圾回收的频率。

5 占用空间

6 反应时间(promptness):对象从垃圾被回收到内存可用的时间。


自己的理解:有的应用系统对暂停对时间要求比较短,那就应该减少垃圾收集在整个周期的抖动,如果应用程序对内存空间占用要求比较苛刻,那么就应该尽量的减少内存空间。


垃圾回收的分代收集:现在几乎所有的jvm都采用分代收集技术,内存被分为多个代,这里最常用的就是分为两代:年轻代,年老代。


不同的代有不同的垃圾回收的算法,每个算法都是基于每个代代特性所优化代。java语言(不止java)有下面两个特征:

1 大部分的分配对象不会被引用很长时间

2 另外一个就是年老的对象引用年轻的对象是很少见的。

年轻代经过几次收集后(这个次数是可以配置的)会被晋升(promoted)到年老代。一般都会给年老代分配相对大的内存,年老代代增长速度是很慢的,所以年老代的垃圾回收的频率很低,但是每次需要相对长的时间。年轻代则相反。

第三章 垃圾回收的一些概念