用户工具


内存为何要分年轻代,老年代? 按回收率对数据分块,而制定不同的回收策略

数据存活判断

  • 引用计数(引用为次数为0的认为是垃圾数据,可以被删除)
    • 缺点:无法判断垃圾对象的循环引用
  • 可达性分析(Reachability Analysis)
    • 从GC Roots开始向下搜索,搜索所走过的路径称为引用链。当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。不可达对象。
    • (java使用该方法)

垃圾回收算法

  • 复制算法
    • 将内存分成2份,每次只是用其中一份。
    • 一定时间后将存活的对象移动到另一块内存(并放一起,避免内存碎片)
    • 然后是用新的那块内存,旧那块内存删除。然后循环是用2块内存
    • 优点:适用于少量对象存活的情况,否则大量移动对象,性能很查
    • 缺点:浪费一半内存
  • 标记-清除
    • 标记阶段:将不可达的对象标记为垃圾
    • 清除阶段:删除垃圾对象
    • 问题:多次回收垃圾后,会有内存碎片问题
  • 标记-压缩
    • 标记阶段:将不可达的对象标记为垃圾
    • 压缩阶段:将可用对象挪到一起(压缩的意思就是吧七零八落的对象放一起,避免内存碎片的问题),然后统一删掉其他垃圾
    • 优点:吞吐量大

收集器

Serial收集器

  • 串行收集器是最古老,最稳定以及效率高的收集器,可能会产生较长的停顿。
    • 只使用一个线程去回收。新生代、老年代使用串行回收;
    • 新生代复制算法
    • 老年代标记-压缩
  • 参数控制:-XX:+UseSerialGC

CMS收集器

  • 他的理念是在运行时回收,尽量减少gc导致的暂停的时间,所以他使用标记-清除算发,因为标记-压缩算法需要移动内存碎片,会导致更多的暂停时间
  • 缺点:因为和用于线程一起运行,所以吞吐量不高
  • 缺点:经过多次full gc之后,会产生大量碎片,还是会经过一次压缩操作,导致内存停顿
    • -XX:+UseConcMarkSweepGC
    • -XX:+ UseCMSCompactAtFullCollection Full GC后,进行一次碎片整理;整理过程是独占的,会引起停顿时间变长
    • -XX:+CMSFullGCsBeforeCompaction 设置进行几次Full GC后,进行一次碎片整理
    • -XX:ParallelCMSThreads 设定CMS的线程数量(一般情况约等于可用CPU数量)

并行收集器

  • 新生代使用复制算法(新生代一般只有少量对象存活,适用于复制算法)
  • 老年代使用标记-压缩
  • +UseParallelGC
    • 新生代并行+老年代并行
  • -UseParallelOldGC
    • 新生代并行+老年代串行

G1收集器

不同于其他的分代回收算法、G1将堆空间划分成了互相独立的区块。每块区域既有可能属于O区、也有可能是Y区,且每类区域空间可以是不连续的。这种将O区划分成多块的理念源于:当并发后台线程寻找可回收的对象时、有些区块包含可回收的对象要比其他区块多很多。虽然在清理这些区块时G1仍然需要暂停应用线程、但可以用相对较少的时间优先回收包含垃圾最多区块。这也是为什么G1命名为Garbage First的原因:第一时间处理垃圾最多的区块。 引用:http://ifeve.com/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3g1%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86%E5%99%A8/

  • -XX:+UseG1GC
  • -XX:MaxGCPauseMillis=200 设置期望的暂停时间