一、如何确定某个对象是“垃圾”?

目前主流垃圾回收器都采用的是可达性分析算法来判断对象是否已经存活,不使用引用计数算法判断对象时候存活的原因在于该算法很难解决相互引用的问题。如何确定对象是否为“垃圾”在前边已经详细说了,现在就不说了。

二、典型的垃圾收集算法

在确定了哪些垃圾可以被回收后,垃圾收集器要做的事情就是开始进行垃圾回收,但是这里面涉及到一个问题是:如何高效地进行垃圾回收。由于Java虚拟机规范并没有对如何实现垃圾收集器做出明确的规定,因此各个厂商的虚拟机可以采用不同的方式来实现垃圾收集器,所以在此只讨论几种常见的垃圾收集算法的核心思想。

1.Mark-Sweep(标记-清除)算法

这是最基础的垃圾回收算法,之所以说它是最基础的是因为它最容易实现,思想也是最简单的。标记-清除算法分为两个阶段:标记阶段清除阶段。标记阶段的任务是标记出所有需要被回收的对象,清除阶段就是回收被标记的对象所占用的空间。具体过程如下图所示:

从图中可以很容易看出标记-清除算法实现起来比较容易, 但该算法不涉及对象移动 ,有一个比较严重的问题就是容易产生内存碎片,碎片太多可能会导致后续过程中需要为大对象分配空间时无法找到足够的空间而提前触发新的一次垃圾收集动作。

2.Copying(复制)算法

  为了解决Mark-Sweep算法的缺陷,Copying算法就被提了出来。它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用的内存空间一次清理掉,这样一来就不容易出现内存碎片的问题。具体过程如下图所示:

这种算法虽然实现简单,运行高效且不容易产生内存碎片,但是却对内存空间的使用做出了高昂的代价,因为能够使用的内存缩减到原来的一半。很显然,Copying算法的效率跟存活对象的数目多少有很大的关系,如果存活对象很多,那么Copying算法的效率将会大大降低。

目前open JDK新生代回收策略就是采用的复制算法,其中Eden和Survivor的默认配置为8:1

3.Mark-Compact(标记-整理)算法(压缩法)

为了解决Copying算法的缺陷,充分利用内存空间,提出了Mark-Compact算法。该算法标记阶段和Mark-Sweep一样,但是在完成标记之后,它不是直接清理可回收对象,而是将存活对象都向一端移动,然后清理掉端边界以外的内存。具体过程如下图所示:

4.Generational Collection(分代收集)算法

分代收集算法是目前大部分JVM的垃圾收集器采用的算法。它的核心思想是根据对象存活的生命周期将内存划分为若干个不同的区域。一般情况下将堆区划分为老年代(Tenured Generation)和新生代(Young Generation),老年代的特点是每次垃圾收集时只有少量对象需要被回收,而新生代的特点是每次垃圾回收时都有大量的对象需要被回收,那么就可以根据不同代的特点采取最适合的收集算法。

目前大部分垃圾收集器对于新生代都采取复制算法,因为新生代中每次垃圾回收都要回收大部分对象,也就是说需要复制的操作次数较少,但是实际中并不是按照1:1的比例来划分新生代的空间的,一般来说是将新生代划分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden空间和其中的一块Survivor空间,当进行回收时,将Eden和Survivor中还存活的对象复制到另一块Survivor空间中,然后清理掉Eden和刚才使用过的Survivor空间。

而由于老年代的特点是每次回收都只回收少量对象,一般使用的是标记-整理算法(压缩法)。

各种算法性能比较

三、典型的垃圾收集器

垃圾收集算法是 内存回收的理论基础,而垃圾收集器就是内存回收的具体实现。下面介绍一下HotSpot(JDK 7)虚拟机提供的几种垃圾收集器,用户可以根据自己的需求组合出各个年代使用的收集器。

垃圾回收器分类:

总体上可以把Java的垃圾回收器分为3类:

串行垃圾回收器(Serial Garbage Collector)

并行垃圾回收器(Parallel Garbage Collector)

并发标记扫描垃圾回收器(CMS Garbage Collector)

1.Serial/Serial Old收集器 是最基本最古老的收集器,它是一个单线程收集器,并且在它进行垃圾收集时,必须暂停所有用户线程。Serial收集器是针对新生代的收集器,采用的是Copying算法,Serial Old收集器是针对老年代的收集器,采用的是Mark-Compact算法。它的优点是实现简单高效,但是缺点是会给用户带来停顿。

2.ParNew收集器 是Serial收集器的多线程版本,使用多个线程进行垃圾收集。

3.Parallel Scavenge收集器 是一个新生代的多线程收集器(并行收集器),它在回收期间不需要暂停其他用户线程,其采用的是Copying算法,该收集器与前两个收集器有所不同,它主要是为了达到一个可控的吞吐量。

4.Parallel Old收集器 是Parallel Scavenge收集器的老年代版本(并行收集器),使用多线程和Mark-Compact算法。

5.CMS(Current Mark Sweep)收集器 是一种以获取最短回收停顿时间为目标的收集器,它是一种并发收集器,采用的是Mark-Sweep算法。

6.G1收集器 是当今收集器技术发展最前沿的成果,它是一款面向服务端应用的收集器,它能充分利用多CPU、多核环境。因此它是一款并行与并发收集器,并且它能建立可预测的停顿时间模型。


详细说说CMS与G1:

一、CMS(Concurrent Mark Sweep)收集器

CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。

CMS 收集器是一种 采用“标记 - 清除” 算法实现的,它的运作过程相比于前面几种垃圾收集器来说更加复杂一些。整个过程分为四个步骤:

(1)初始标记: 暂停所有的其他线程,并记录下直接与 root 相连的对象,速度很快 ;(会引起“Stop The World”)

(2)并发标记: 同时开启 GC 和用户线程,用一个闭包结构去记录可达对象。但在这个阶段结束,这个闭包结构并不能保证包含当前所有的可达对象。因为用户线程 可能会不断的更新引用域,所以 GC 线程无法保证可达性分析的实时性。所以这个算法里会跟踪记录这些发生引用更新的地方。

(3)重新标记: 重新标记阶段就是为了修正并发标记期间因为用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段的时间稍长,远远比并发标记阶段时间短。 (会引起“Stop The World”)

(4)并发清除: 开启用户线程,同时 GC 线程开始对为标记的区域做清扫

CMS收集器主要优点:

  • 并发收集;
  • 低停顿。

CMS四个明显的缺点:

(1) 垃圾碎片的问题 ,我们都知道CMS是使用的是 标记-清除 算法的,所以不可避免的就是会出现垃圾碎片的问题。

(2)耗时,一般CMS的GC耗时80%都在remark阶段,remark阶段停顿时间会很长 ,在CMS的这四个主要的阶段中,最费时间的就是重新标记阶段。

(3)concurrent mode failure,这个异常发生在cms正在回收的时候。执行CMS GC的过程中,同时业务线程也在运行,当年轻带空间满了,执行ygc时,需要将存活的对象放入到老年代,而此时老年代空间不足,这时CMS还没有机会回收老年带产生的,或者在做Minor GC的时候,新生代救助空间放不下,需要放入老年代,而老年代也放不下而产生的

(4)promotion failed ,这个问题是指,在进行Minor GC时,Survivor空间不足,对象只能放入老年代,而此时老年代也放不下造成的,多数是由于老年代有足够的空闲空间,但是由于碎片较多,新生代要转移到老年带的对象比较大,找不到一段连续区域存放这个对象导致的。

二、 G1垃圾回收器

G1 (Garbage-First) 是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器。以极高概率满足 GC 停顿时间要求的同时,还具备高吞吐量性能特征.

特点:

(1)并行与并发:G1 能充分利用 CPU、多核环境下的硬件优势,使用多个 CPU(CPU 或者 CPU 核心)来缩短 Stop-The-World 停顿时间。部分其他收集器原本需要停顿 Java 线程执行的 GC 动作,G1 收集器仍然可以通过并发的方式让 java 程序继续执行。

(2)分代收集:虽然 G1 可以不需要其他收集器配合就能独立管理整个 GC 堆,但是还是保留了分代的概念。

(3)空间整合:与 CMS 的 “标记 – 清理” 算法不同,G1 从整体来看是基于 “标记整理” 算法实现的收集器;从局部上来看是基于 “复制” 算法实现的。

(4)可预测的停顿:这是 G1 相对于 CMS 的另一个大优势,降低停顿时间是 G1 和 CMS 共同的关注点,但 G1 除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为 M 毫秒的时间片段内。

G1收集器的阶段分以下几个步骤:

1、初始标记(它标记了从GC Root开始直接可达的对象);

2、并发标记(从GC Roots开始对堆中对象进行可达性分析,找出存活对象);

3、最终标记(标记那些在并发标记阶段发生变化的对象,将被回收);

4、筛选回收(首先对各个Regin的回收价值和成本进行排序,根据用户所期待的GC停顿时间指定回收计划,回收一部分Region)。

参考资料:《深入理解Java虚拟机》

垃圾回收算法_Java 垃圾回收算法与几种垃圾回收器相关推荐

  1. java gc回收算法_Java GC回收算法-判定一个对象是否可以回收

    开源推荐 推荐一款一站式性能监控工具(开源项目) Pepper-Metrics是跟一位同事一起开发的开源组件,主要功能是通过比较轻量的方式与常用开源组件(jedis/mybatis/motan/dub ...

  2. java 回收策略_Java堆回收策略

    一.起源 1960年Lisp语言: 第一门真正使用内存动态分配和垃圾回收的语言. 二.概要 线程相关:程序计数器.虚拟机栈.本地方法栈,不需要考虑垃圾回收 Java堆.方法区:需要考虑垃圾回收 三.垃 ...

  3. java回溯算法_java实现回溯算法

    最近有在leetcode上面做算法题,已经遇到了两道回溯算法的题目,感觉一点思路都没有,现决定将java如何实现回溯算法做一次总结. 什么叫做回溯算法 (摘抄于百度百科) 回溯算法实际上一个类似枚举的 ...

  4. java常用算法_JAVA编程常用算法——冒泡排序

    一.冒泡排序算法运作的过程 (1)比较相邻的元素.如果第一个比第二个大,就交换他们两个. (2)对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对.在这一点,最后的元素应该会是最大的数. (3 ...

  5. java密码学原型算法_java密码学原型算法实现——双线性对.pdf

    java密码学原型算法实现--双线性对 Java 密码学原型算法实现--双线性对 1.背景介绍 如何使用jPBC 库进行双线性群初始化,包括: (1)质数阶双线性群(Prime-Order Bilin ...

  6. java二叉树算法_java构建二叉树算法

    展开全部 //********************************************************************************************* ...

  7. java 有向图 最短路径算法_java使用Dijkstra算法实现单源最短路径

    单源最短路径问题,即在图中求出给定顶点到其它任一顶点的最短路径.在弄清楚如何求算单源最短路径问题之前,必须弄清楚最短路径的最优子结构性质. 一.最短路径的最优子结构性质 该性质描述为:如果P(i,j) ...

  8. java kmp算法_java实现KMP算法

    第一种 暴力移位(效率低,资源浪费) 第二种KMP算法 这是直接盗用老师ppt中的内容,意思大家明白就好了,看代码: public class KMP { public int Index_KMP(S ...

  9. java美颜算法_java实现各种算法

    package sortAlgorithm; import java.io.File; import java.io.IOException; import java.sql.Time; import ...

  10. java 蚁群算法_Java蚁群算法(Ant Colony)求解旅行商问题(TSP)(二)

    算法准备 旅行商问题(TSP)是一个经典的图论问题.在给定一系列城市和他们之间的距离以后,一个旅行商人希望能够找到一条能够走遍所有城市,并返回起点城市的最短路径.既然路径能串起来所有的城市,那么问题中 ...

最新文章

  1. 基于交换技术的网络中,全双工主要运行在?( 内有答案与详解)
  2. 2.10 局部最优的问题-深度学习第二课《改善深层神经网络》-Stanford吴恩达教授
  3. java.lang.IllegalArgumentException: Can not set XXX to com.sun.proxy.$Proxy28
  4. Python学习day02_数字类型 与 布尔类型 短路逻辑和运算符优先级
  5. android tv 帮助,android TV端各类焦点问题
  6. 批处理(bat)实现SQLServer数据库备份与还原
  7. SAP License:数据导入时的问题与总结
  8. 为什么科学家这么痴迷于研究僵尸?
  9. git 停止维护了,官网无法下载
  10. SqlDependency不起作用
  11. 安卓电视 TV端的webview网页 按键控制和一些小问题
  12. 一部手机即可轻松玩转抖音四大主流变现方式——匀思电商
  13. 万洲金业:白银继续走高,预期缓慢冲高
  14. Windows使用CMD命令查看WIFI密码
  15. H5和C3新特性(完整版)
  16. Python数据分析项目-共享单车骑行数据分析
  17. WPF 从 dotnet core 3 到 dotnet 5 的变更
  18. VMware安装mac的流程及unlocker 报错 、出现的一些问题解决方案整理
  19. 如何用python处理pdf_用Python处理PDF
  20. 洛谷:P1033 [NOIP2002 提高组] 自由落体 C++详解

热门文章

  1. 5.21工作记录(修改页面跳转,去掉多余的js;增加图片清除功能)
  2. DOM——获取元素的方式
  3. 浅入深出Vue:环境搭建
  4. [oc学习日记]代理模式
  5. pycharm创建python虚拟环境好处_PyCharm虚拟环境创建Django2项目一些问题的解决方案...
  6. markdown 流程图js_在Markdown中用mermaid语法绘制图表
  7. java jdbc 传参_java – 将参数传递给JDBC PreparedStatement
  8. c++的lambda表达式捕获this_贯穿 C++ 11 与 C++ 17 的 Lambda 到底是个什么?
  9. 利用双向循环链表实现长整数的存储_重学数据结构之链表篇
  10. linux快速删除60万文件,Linux下快速删除大量文件