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

这一小节先了解一个最基本的问题:如果确定某个对象是“垃圾”?既然垃圾收集器的任务是回收垃圾对象所占的空间供新的对象使用,那么垃圾收集器如何确定某个对象是“垃圾”?通过什么方法判断一个对象可以被回收了。

在java中是通过引用来和对象进行关联的,也就是说如果要操作对象,必须通过引用来进行。那么很显然一个简单的办法就是通过引用计数来判断一个对象是否可以被回收。不失一般性,如果一个对象没有任何引用与之关联,则说明该对象基本不太可能在其他地方被使用到,那么这个对象就成为可被回收的对象了。这种方式成为引用计数法

这种方式的特点是实现简单,而且效率较高,但是它无法解决循环引用的问题,因此在Java中并没有采用这种方式(Python采用的是引用计数法)。

为了解决这个问题,在Java中采取了可达性分析法。该方法的基本思想是通过一系列的“GC Roots”对象作为起点进行搜索,如果在“GC Roots”和一个对象之间没有可达路径,则称该对象是不可达的,不过要注意的是被判定为不可达的对象不一定就会成为可回收对象。被判定为不可达的对象要成为可回收对象必须至少经历两次标记过程,如果在这两次标记过程中仍然没有逃脱成为可回收对象的可能性,则基本上就真的成为可回收对象了。

二、典型的垃圾收集算法

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

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

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

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

2.Copying(复制)算法

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

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

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)虚拟机提供的几种垃圾收集器,用户可以根据自己的需求组合出各个年代使用的收集器。

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(Concurrent Mark Sweep)收集器 是一种以获取最短回收停顿时间为目标的收集器,它是一种并发收集器,采用的是Mark-Sweep算法。

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

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

Java 垃圾回收机制与几种垃圾回收算法相关推荐

  1. java垃圾回收机制串行_Java垃圾回收机制

    Java语言是一门自动内存管理的语言,不再需要的对象可以通过垃圾回收自动进行内存释放. Java运行时内存区域划分 JVM将Java程序运行时内存区域划分成以下几个部分: 程序计数器(Program ...

  2. java gc回收机制种类_JAVA的垃圾回收机制(GC)

    1.什么是垃圾回收? 垃圾回收(Garbage Collection)是Java虚拟机(JVM)垃圾回收器提供的一种用于在空闲时间不定时回收无任何对象引用的对象占据的内存空间的一种机制. 2.什么时候 ...

  3. C++中垃圾回收机制中几种经典的垃圾回收算法

    前言 垃圾收集器是一种动态存储分配器,它自动释放程序不再需要的已分配的块,这些块也称为 垃圾 .在程序员看来,垃圾就是不再被引用的对象.自动回收垃圾的过程则称为 垃圾收集(garbage collec ...

  4. Java语言垃圾回收机制是什么_Java垃圾回收机制简述

    Java垃圾回收机制简述 发布时间:2020-08-22 19:50:29 来源:脚本之家 阅读:64 作者:海子 说到垃圾回收(Garbage Collection,GC),很多人就会自然而然地把它 ...

  5. java垃圾回收机制标记_Java的垃圾回收机制-垃圾收集算法(一)

    当需要排查各种内存溢出,内存泄漏等问题时,当垃圾收集成为系统达到更高并发的瓶颈时,我们有必要深入GC的原理. image.png 常见垃圾回收算法 在查看垃圾回收具体过程的时候,运行程序加上: -XX ...

  6. javascript 垃圾回收机制--分代式垃圾回收机制

    以前对 javascript 的垃圾回收机制没有深入了解过.以为只是简单的标记清除法.即从根对象开始找它的引用,然后依次往后找它引用的引用,依次递归,将所有被引用的变量打上标记.然后在遍历完后,清除没 ...

  7. 简述python垃圾回收机制_python中的垃圾回收机制简述

    2020年12月5日21:47:35 王凯玉 python中的垃圾回收机制 引用计数 # 引用计数 引用计数是编程语言中的一中内存管理技术,可以将资源的被引用次数保存起来. 当引用计数为0时,资源将被 ...

  8. jvm垃圾回收机制_干货|JVM垃圾回收机制

    前言 不同于C++程序员必须自己完成内存的分配.使用和释放,JAVA语言提供了垃圾回收机制(GC,Garbage Collection),所以JAVA程序员仅需要负责分配和使用内存即可,而释放内存则由 ...

  9. php7垃圾回收机制l_php5和php7垃圾回收上的区别是什么?

    php5和php7垃圾回收上的区别 PHP5和PHP7的垃圾回收机制都属于引用计数,但是在复杂数据类型的算法处理上:PHP7中zval有了新的实现方式. 最基础的变化就是 *zval 需要的内存不再是 ...

最新文章

  1. Spartan-6的I/O时钟缓冲器
  2. Oracle将关闭Java.net和Kenai.com社区
  3. 光在介质中传播速度—材料折射率变化—物理光学记录
  4. Java 多线程三大核心
  5. C语言结构体占用内存总结
  6. Extension project - Component.js of standard application could not be loaded
  7. date转timestamp格式_技术分享 | MySQL:timestamp 时区转换导致 CPU %sys 高的问题
  8. Linux 添加计划任务
  9. SVN提交时显示:Path is not a working copy directory
  10. 惠普打印机墨盒更换教程_惠普打印机怎么换墨盒 一不小心就洒了一桌子墨水...
  11. Java多线程+线程池
  12. 国内数字藏品交易平台开发市场会开放二级市场吗
  13. connection reset by peer
  14. python5.网络爬虫
  15. 解决Linux vim 打开文件乱码问题
  16. python七巧板三角形_canvas基础入门(二)绘制线条、三角形、七巧板
  17. 有 50 家人家,每家一条狗。有一天警察通知, 50 条狗当中有病狗,行为和正常狗不一样。每人只能通过观察别 人家的狗来判断自己家的狗是否生病,而不能看自己家的狗,如果判断出自己家的狗病了,就必须当天
  18. freeNAS(网络区域存储)
  19. 柴油闪点不合格的原因
  20. JDBC连接Sql_Server_2005

热门文章

  1. 安卓SDK和API是什么意思?
  2. 如何在现货贵金属白银中超越自我
  3. Edge优质插件分享
  4. 我走了phpchina
  5. 计算机基础的建议,计算机应用基础教学实施建议.docx
  6. iwebshop系统的极速安装
  7. ffmpeg moov 前移命令
  8. 24 基于单片机空气PM2.5浓度粉尘颗粒物检测系统设计
  9. RK3568/RK3566 mipi双摄调试(gc2093+gc2053)
  10. ChatGPT 实现对twitter、微博内容的扩、缩写,主题词的提取,以及话题的标签格式化。