java垃圾回收机制

 垃圾回收的几种基本算法:
1.引用计数
此对象有一个引用,则增加一个计数,删除一个引用,则减少一个计数。当计数为零的时候,则是无用对象,将被回收。缺陷:无法处理循环引用的问题,并且计数器增加了程序执行的开销。
2.标记-清除
使用了根集的概念。垃圾回收器从根集开始扫面,识别出哪些对象可达,哪些对象不可达。并用某种方式标记可达对象,例如对每个可达对象设置一个活多个位。将未被标记的对象删除。缺陷:要暂停整个应用,并会产生内存碎片。
3复制
为了解决堆碎片问题。将内存分成两部分,每次便利使用区域,将活动的对象复制到另一区域,然后回收剩下的对象。同时堆复制过去以后还能进行相应的内存整理,这样就不会出现内存碎片问题。缺陷:需要更多的内存空间。
4标记-整理
此算法结合了标记-清除和复制的有点。分成两个阶段,第一个阶段从根节点开始标记所有活动对象。第二阶段遍历整个堆,清除未标记对象并将标记对象“压缩”到堆的其中一块,按顺序排放。此算法避免了碎片问题且不需要额外的内存空间。
5增量收集
实时垃圾回收算法。在应用进行的同时进行垃圾回收。
6分代
基于对对象生命周期分析后得出的垃圾回收算法。把对象分为年轻带,年老代,持久带。对不同生命周期的对象使用不同的算法(上述方式中的一种)进行回收。
年轻代:包括一个Eden区,两个 Survivor区。大部分对象在Eden区生成,当Eden区满时,还存活的对象将移到Survivor区(两个Survivor区中的一个),当这个Survivor区也满时,还存活的对象将移到另一个Survivor区,当这个Survivor也满时,从第一个Survivor区来的对象还存活的话,就移到老年代。注意:链各个Survivor区没有先后关系,是对称的,总有一个是空的。
老代:存放从年轻代移过来的对象,存活的都是比较久的对象。
持久代:用于存放静态文件,如java类,方法等。持久带对垃圾回收没有显著地影响。

GC类型: Scavenge GC 和Full GC
1.Scavenge GC:当新对象生成,并且在Eden区申请失败的时候将会出发Scavenge GC。将会遍历整个Eden区,将活动的对象移到Survivor区,回收不活动的对象。并整理两个Survivor区。
2.Full GC:遍历整个堆,包括年轻代,年老代和持久代。速度比Scanvenge GC慢很多,所以尽量减少Full GC.
造成Full GC的原因:
     1.年老代被写满
     2.持久代被写满
     3.显示调用System.GC
     4.上一个GC后个heap的各域分配策略动态变化。

垃圾回收器:串行收集器,并行收集器,并发收集器
1.串行收集器:使用单线程处理所有的垃圾回收工作,因为无需多线程交互,所以效率比较高。但是,也无法使用多处理器的优势,所以此收集器适合单处理器机器,也可用在小数据量(100M)情况下的多处理器上。可以使用 -XX:+UseSerialGC打开。
2.并行收集器:对年轻代进行垃圾回收,因此可以减少垃圾回收时间。一般在多线程多处理器上使用。使用XX:+UseParallelGC打开。在Java SE6.0中进行了增强--可以在堆年老代进行并行收集。如果年老代不进行并发收集的话,是使用单线程进行垃圾回收,因此会制约扩展能力,使用-XX:+UseParallelOldGC。应用响应的时间比较长。
    使用-XX:ParallelGCThreads=设置并行垃圾回收的线程数。此值可以设置与机器处理器数量相等。
      此收集器可进行如下配置:
          1.最大垃圾回收暂停:指定垃圾回收的最长暂停时间,通过-XX:MaxGCPauseMillis=指定。为毫秒,如果指定了此值,堆大小和垃圾回收参数会进行调整以达到指定值。设定此值可能减少应用的吞吐量。
          2.吞吐量:垃圾回收时间和非垃圾回收时间的比值。通过-XX:GCTimeRatio=设定,公式为1/(1+N)。例如,-XX:GCTimeRatio=9时,表示10%的时间用于垃圾回收。默认为99,即1%的时间用于垃圾回收。
3.并发收集器:可以保证大部分工作都并发进行(应用部停止),垃圾回收只暂停很短的时间,此收集器适合对响应时间要求比较高的中,大规模应用。使用-XX:+UserConcMarkSweepGC打开。
      并发收集器主要减少年老代的暂停时间,他在应用不停止的情况下使用独立的垃圾回收线程,跟踪可达对象。在每个年老代垃圾回收周期中,在收集初期并发收集器会对整个应用进行简短的暂停,在收集中还会再暂停一次。第二次暂停会比第一次稍长,在此过程中多个线程同时进行垃圾回收工作。
      并发收集器使用 处理器换来短暂的停顿时间 。在一个N个处理器的系统上,并发收集部分使用 K/N 个可用处理器进行回收,一般情况下 1<=K<=N/4
      在只有 一个处理器的主机上使用并发收集器 ,设置为 incremental mode 模式也可获得较短的停顿时间。
      浮动垃圾 :由于在应用运行的同时进行垃圾回收,所以有些垃圾可能在垃圾回收进行完成时产生,这样就造成了“Floating Garbage”,这些垃圾需要在下次垃圾回收周期时才能回收掉。所以,并发收集器一般需要 20% 的预留空间用于这些浮动垃圾。
       Concurrent Mode Failure :并发收集器在应用运行时进行收集,所以需要保证堆在垃圾回收的这段时间有足够的空间供程序使用,否则,垃圾回收还未完成,堆空间先满了。这种情况下将会发生“并发模式失败”,此时整个应用将会暂停,进行垃圾回收。
      启动并发收集器 :因为并发收集在应用运行时进行收集,所以必须保证收集完成之前有足够的内存空间供程序使用,否则会出现“Concurrent Mode Failure”。通过设置 -XX:CMSInitiatingOccupancyFraction= 指定还有多少剩余堆时开始执行并发收集


  1. 常见配置汇总
    1. 堆设置
      • -Xms:初始堆大小
      • -Xmx:最大堆大小
      • -XX:NewSize=n:设置年轻代大小
      • -XX:NewRatio=n:设置年轻代和年老代的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4
      • -XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5
      • -XX:MaxPermSize=n:设置持久代大小
    2. 收集器设置
      • -XX:+UseSerialGC:设置串行收集器
      • -XX:+UseParallelGC:设置并行收集器
      • -XX:+UseParalledlOldGC:设置并行年老代收集器
      • -XX:+UseConcMarkSweepGC:设置并发收集器
    3. 垃圾回收统计信息
      • -XX:+PrintGC
      • -XX:+PrintGCDetails
      • -XX:+PrintGCTimeStamps
      • -Xloggc:filename
    4. 并行收集器设置
      • -XX:ParallelGCThreads=n:设置并行收集器收集时使用的CPU数。并行收集线程数。
      • -XX:MaxGCPauseMillis=n:设置并行收集最大暂停时间
      • -XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)
    5. 并发收集器设置
        • -XX:+CMSIncrementalMode:设置为增量模式。适用于单CPU情况。
        • -XX:ParallelGCThreads=n:设置并发收集器年轻代收集方式为并行收集时,使用的CPU数。并行收集线程数。

调优总结

  1. 年轻代大小选择
    • 响应时间优先的应用尽可能设大,直到接近系统的最低响应时间限制(根据实际情况选择)。在此种情况下,年轻代收集发生的频率也是最小的。同时,减少到达年老代的对象。
    • 吞吐量优先的应用:尽可能的设置大,可能到达Gbit的程度。因为对响应时间没有要求,垃圾收集可以并行进行,一般适合8CPU以上的应用。
  2. 年老代大小选择
    • 响应时间优先的应用:年老代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率会话持续时间等一些参数。如果堆设置小了,可以会造成内存碎片、高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较长的收集时间。最优化的方案,一般需要参考以下数据获得:
      • 并发垃圾收集信息
      • 持久代并发收集次数
      • 传统GC信息
      • 花在年轻代和年老代回收上的时间比例
      减少年轻代和年老代花费的时间,一般会提高应用的效率
    • 吞吐量优先的应用:一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代。原因是,这样可以尽可能回收掉大部分短期对象,减少中期的对象,而年老代尽存放长期存活对象。
  3. 较小堆引起的碎片问题
    因为年老代的并发收集器使用标记、清除算法,所以不会对堆进行压缩。当收集器回收时,他会把相邻的空间进行合并,这样可以分配给较大的对象。但是,当堆空间较小时,运行一段时间以后,就会出现“碎片”,如果并发收集器找不到足够的空间,那么并发收集器将会停止,然后使用传统的标记、清除方式进行回收。如果出现“碎片”,可能需要进行如下配置:
    • -XX:+UseCMSCompactAtFullCollection:使用并发收集器时,开启对年老代的压缩。
    • -XX:CMSFullGCsBeforeCompaction=0:上面配置开启的情况下,这里设置多少次Full GC后,对年老代进行压缩


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值