垃圾回收的算法与方式

来源:互联网 发布:java逆序输出数组 编辑:程序博客网 时间:2024/05/16 08:33

    垃圾回收的基本算法:1、引用计数(reference counting)此对象有一个引用,则增加一个计数,删除一个引用则减少一个计数,垃圾回收只回收计数为0的对象;2、标记-清除(mark-sweep)从引用的根节点来标记所有的对象,遍历整个节点,把未标记的清除;3、复制(copying       )遍历整个区域,把正在使用的对象复制到其它区域。4、标记-整理(mark-compact)从根节点标记所用对象,遍历整个堆,清除未标记的对象并把正在使用的对象“压缩”到堆的一个区域,按顺序排放;5、增量收集(incremental collecting)在应用进行的同时进行垃圾回收;6、分代(generational collecting)把垃圾分为年轻代,年老代,持久代,对不同的生命同期的对象安上述算法之一进行垃圾回收。

    下面说一下各个生命周期的垃圾:

年轻代,它分为一个eden(伊甸园)和两个survivor(复活)区,大部分的对象在eden区,当eden区满时,再把存活的对象复制到survivor区的一个,当这个survivor满时,此区存活的对象再复制到survivor的另一个区,当这个survivor满时再把从第一个survivor区复制过来的仍然存活的对象复制到tenured(年老代),需要注意的是两个survivor是对称的,没有前后关系,同一个survivor区可能有从eden区中复制过来的存活对象,也有从另一个survivor区中复制过来的存活对象。

年老代,存放的是从年轻代复制过来的存活的对象,年老代的对象一般都是生命周期较长的对象。

持久代(perm)一般存放一些静态文件,比如java类,方法等,持久代对垃圾回收没有显著影响,有些应用或动态生成一些class比如Hibernate,需要开辟一些持久的空间来存放这些运行过程中的新增类,持久代的大小是通过-XX:MaxPermSize=<N>进行设置。

GC的情况:一般的情况是,当新对象生成时,在eden区审请空间失败时就触发GC,即minorGC,对堆eden非存活对象进行清除,并把存活的对象复制到survivor区,然后整理两个survivor区。

 

垃圾回收器的三种方式:

一、串行收集器(serialGC):使用单线程处理所有的垃圾回收工作,无需多线程交互,所以效率比较高,当然也无法使用多处理器的优势,此收集器适用于单处理器,对小数据量(100M)的多处理器也适用。-XX:+UseSerialGC打开。

二、并行收集器(ParallelGC),对于年轻代用并行收集器,可以减少垃圾回收的时间,一般在多线程,多处理器上使用,使用-XX:+UseParallelGC打开,并行收集器在J2SE5上引用,在J2SE6上得到增强,并且可以在年老代运用并行收集器,如果老年代不运用并发收集的话,只有用单线程进行处理,这样会制约扩展能力,作用-XX:+UseParalleOldGC打开,使用-XX:ParallelGCThreads=<N>进行并行线程数的设置。可以设置成与机器处理器的数量相等。

-XX:MaxGCPauseMillis=<N>,设置 为毫秒,为最长垃圾收集暂停时间,通过堆大小以及垃圾收集的相关参数的设置可达到相应的值,设置此值可以减少垃圾回收的吞吐量,吞吐量指垃圾回收时间与非回收时间的比值。-XX:GCTimeRatio=<N>设置吞吐量,默认为99,即用1%的时间进行垃圾回收。

三、并发收集器(ConcMarkSweepGC):

垃圾收集进行并发进行,应用不停止,这种情况适用于对响应时间要求高,大规模的应用。使用-XX:+UseConcMarkSweepGC打开。并发收集器主要是减少年老代的暂停时间,在并发收集的初期有一次短暂的暂停,在收集过程中也有一次暂停,此次比第一次长。它是用多处理器来换取更短暂的停顿时间。

如果在单处理器上使用并发收集,可以作用incremental model来获取更少的停留时间。

并发收集器要预留20%的空间来给浮动垃圾,所谓浮动垃圾就是在垃圾收集器进行处理的时候产生的垃圾,这种垃圾要在下一次垃圾处理的时候进行收集。

并发收集器要在应用进行中进行垃圾收集,所以要保证堆在垃圾回收的这段时间有足够的空间供应用使用,不然垃圾还未收完,堆就满了,这就会引起“并发模式失败”(concurrentMode failure),此时整个应用就会暂停,进行垃圾回收。

为了避免并发模式失败,在保证收集完成之前,有足够的空间供程序使用,可以设置它:-XX:CMSInitiatingOccupancyFraction=<N>

指定还有多少剩余堆时开始执行并发收集。

 

JVM中最大堆有三方面的限制:

1、         相关操作系统数据模型的限制(32bit-64bit)

2、         系统可用的虚拟内存的限制

3、         系统可用的物理内存的限制

32bit系统下一般需要1-2G;64bit系统对内存无限制要求

原创粉丝点击