JVM垃圾回收算法

守給你的承諾、 提交于 2020-01-10 13:48:11

转:https://www.cnblogs.com/godoforange/p/11552865.html

如何判断对象是否为垃圾对象?

1)引用计数法

在对象中添加一个引用计数器,当有地方引用这个对象的时候,引用技术器得值就+1,当引用失效的时候,计数器得值就-1
算法缺点:循环引用无法回收。

2)可达性分析法

GCroot结点开始向下搜索,路径称为引用链,当对象没有任何一条引用链链接的时候,就认为这个对象是垃圾,并进行回收。

那么什么是GCroot呢(虚拟机在哪查找GCroot)。

  • 虚拟机栈(局部变量表)
  • 方法区的类属性所引用的对象。
  • 方法区中常量所引用的对象。
  • 本地方法栈中引用的对象。

目前主流JVM采用的垃圾判定算法就是可达性分析法。

垃圾回收算法:

1)标记-清除算法

存在的问题:

  • 效率问题。
  • 内存小块过多。
    如图所示:黄色的就是被标记清除的。清除后会发现有很多多余的小块。

2)复制算法

下面是java内存常规划分

  • (线程共有)堆内存 方法区
  • (栈内存 本地方法栈) 程序计数器

下面是堆内存的划分

  • 新生代
    • Eden 伊甸园
    • Survivor 存活区
    • Tenured Gen 养老区
  • 老年代

下面就是过程:

被标记的黑色就是需要回收的

将白色区域复制下面,然后清空上面的


这样就完成了内存的连续分配,但是引来一个问题。
每次只能使用一半的内存。是不是有点少。。

为了解决这个问题,我们对内存就进行了划分。
我们对内存分为了三块区域,survivor和Eden的内存占比为1:8。

这里我们即提高了效率,又减少了内存分配。复制算法,我们需要将上面的思路,将Eden中需要回收的对象放到Survivor,然后清除。
也就是俩个Survivor中进行复制与清除。

如果Survivor不够放,那就扔到老年代里,或者其他方法,反正有内存担保。

3)标记-整理算法

复制算法主要针对新生代内存收集方法。
标记-整理算法主要针对的是老年代内存收集方法。

主要步骤:标记-整理-清除

如下图所示

然后将右面的进行删除计科达到回收效果。

4)分代收集算法

分代收集算法是根据内存的分代选择不同的算法。
对于新生代,一般选择复制算法。
对于老年代,一般选择标记-整理-清除算法。

显而易见,这是上面俩种算法的优点糅合在一起的应用。

垃圾收集器

1)Serial收集器

特点:

  • 出现的最早的,发展最悠久的垃圾收集器。
  • 单线程垃圾收集器。
  • 主要针对新生代内存进行收集

运行机制如下所示

缺点:慢

用处:在客户端上运行还是比较有效。没有线程的开销,所以在客户端还是比较好用的。

2)ParNew收集器

特点:

  • 由单线程变成了多线程垃圾收集器。
  • 如果要用CMS进行收集的话,最好采用ParNew收集器。

实现原理都是复制算法。

缺点:

  • 性能较慢

3)Parallel Scavenge 收集器

主用算法:复制算法(新生代收集器)

吞吐量 = (执行用户代码消耗的时间)/(执行用户代码的时间)+ 垃圾回收时所占用的时间

优点:吞吐量优化(CPU用于运行用户代码的时间与CPU消耗的总时间的比值)

关于控制吞吐量的参数如下

Copy
-XX:MaxGCPauseMills #垃圾收集器的停顿时间
-XX:GCTimeRatio #吞吐量大小

当停顿时间过小时,内存对应变小,回收的频率增大。因此第一个参数需要设置的合理才比较好。
第二个参数值越大,吞吐量越大,默认是99,(垃圾回收时间最多只能占到1%)

总的来说:客户端可用,服务端最好不用。

4)CMS收集器(Concurrent Mark Sweep)

采用算法:标记清除算法。

  • 工作过程:
    • 初始标记
    • 并发标记
    • 重新标记
    • 并发清理
  • 优点:
    • 并发收集
    • 低停顿
  • 缺点:
    • 占用大量的CPU资源
    • 无法处理浮动垃圾
    • 出现ConcurrentMode Failure
    • 空间碎片

CMS是一个并发的收集器。

目标是:减少延迟,增加响应速度
执行效果如下所示:

  • 初始标记
    • 可达性分析法
  • 重新标记
    • 为了修正并发期间,因对象重新运作而修正
  • 并发清理
    • 直接清除了

5)G1收集器(面向服务端)

最牛的垃圾收集器。

  • 历史
    -2004年Sun发表了第一篇G1的论文,到2006年左右,在JDK6内集成进去了。JDK7才放出来。
  • 优势
    • 集中了前面所有收集器的优点
    • G1能充分利用了多核的并行特点,能缩短停顿时间。
    • 分代收集(分成各种Region)
    • 空间整合(类似于标记清理算法)
    • 可预测的停顿()。
  • 步骤
    • 初始标记
    • 并发标记
    • 最终标记
    • 筛选回收
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!