众所周知,Java的垃圾回收是不需要程序员去手动操控的,而是由JVM去完成。本文介绍JVM进行垃圾回收的各种算法。

  • 1. 如何确定某个对象是垃圾

    • 1.1. 引用计数法
    • 1.2. 可达性分析
  • 2. 典型的垃圾回收算法
    • 2.1. 标记-清除算法(Mark-Sweep)
    • 2.2. 复制算法(Copying)
    • 2.3. 标记-整理算法(Mark-Compact)
    • 2.4. 分代收集算法(Generational Collection)
  • 3. 典型的垃圾收集器
    • 3.1. Serial/Serial Old
    • 3.2. ParNew
    • 3.3. Parallel Scavenge
    • 3.4. Parallel Old
    • 3.5. CMS
    • 3.6. G1
  • 4. 参考文章

1. 如何确定某个对象是垃圾

1.1. 引用计数法

在Java中,引用和对象是有关联的。如果要操作对象则必须用引用进行。因此,很显然一个简单的办法是通过引用计数来判断一个对象是否可以回收。简单说,即一个对象如果没有任何与之关联的引用,则说明对象不太可能再被用到,那么这个对象就是可回收对象。这种方式即是引用计数法。这种方式的问题是无法解决循环引用的问题,举个例子:

public static void main(String[] args){Object object1=new Object();Object object2=new Object();object1.object=object2;object2.object=object1;object1=null;object2=null;
}

显然,在最后,object1和object2的内存块都不能再被访问到了,但他们的引用计数都不为0,这就会使他们永远不会被清除。

1.2. 可达性分析

为了解决引用计数法的循环引用问题,Java使用了可达性分析的方法。通过一系列的“GC roots”对象作为起点搜索。如果在“GC roots”和一个对象之间没有可达路径,则称该对象是不可达的。要注意的是,不可达对象不等价于可回收对象,不可达对象变为可回收对象至少要经过两次标记过程。两次标记后仍然是可回收对象,则将面临回收。

比较常见的将对象视为可回收对象的原因:

  • 显式地将对象的唯一强引用指向新的对象。
  • 显式地将对象的唯一强引用赋值为Null。
  • 局部引用所指向的对象(如,方法内对象)。

下述代码中,每次循环结束,object都会被视为可回收对象。

void fun() {.....for(int i=0;i<10;i++) {Object obj = new Object();System.out.println(obj.getClass());}
}
  • 只有弱引用与其关联的对象

2. 典型的垃圾回收算法

在JVM规范中并没有明确GC的运作方式,各个厂商可以采用不同的方式去实现垃圾回收器。这里讨论几种常见的GC算法。

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

最基础的垃圾回收算法,分为两个阶段,标注和清除。标记阶段标记出所有需要回收的对象,清除阶段回收被标记的对象所占用的空间。如图:

从图中我们就可以发现,该算法最大的问题是内存碎片化严重,后续可能发生大对象不能找到可利用空间的问题。

2.2. 复制算法(Copying)

为了解决Mark-Sweep算法内存碎片化的缺陷而被提出的算法。按内存容量将内存划分为等大小的两块。每次只使用其中一块,当这一块内存满后将尚存活的对象复制到另一块上去,把已使用的内存清掉,如图:

这种算法虽然实现简单,内存效率高,不易产生碎片,但是最大的问题是可用内存被压缩到了原本的一半。且存活对象增多的话,Copying算法的效率会大大降低。

2.3. 标记-整理算法(Mark-Compact)

结合了以上两个算法,为了避免缺陷而提出。标记阶段和Mark-Sweep算法相同,标记后不是清理对象,而是将存活对象移向内存的一端。然后清除端边界外的对象。如图:

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

分代收集法是目前大部分JVM所采用的方法,其核心思想是根据对象存活的不同生命周期将内存划分为不同的域,一般情况下将GC堆划分为老生代(Tenured/Old Generation)和新生代(Young Generation)。老生代的特点是每次垃圾回收时只有少量对象需要被回收,新生代的特点是每次垃圾回收时都有大量垃圾需要被回收,因此可以根据不同区域选择不同的算法。

目前大部分JVM的GC对于新生代都采取Copying算法,因为新生代中每次垃圾回收都要回收大部分对象,即要复制的操作比较少,但通常并不是按照1:1来划分新生代。一般将新生代划分为一块较大的Eden空间和两个较小的Survivor空间(From Space, To Space),每次使用Eden空间和其中的一块Survivor空间,当进行回收时,将该两块空间中还存活的对象复制到另一块Survivor空间中。

而老生代因为每次只回收少量对象,因而采用Mark-Compact算法。

另外,不要忘记在Java基础:Java虚拟机(JVM)中提到过的处于方法区的永生代(Permanet Generation)。它用来存储class类,常量,方法描述等。对永生代的回收主要包括废弃常量和无用的类。

对象的内存分配主要在新生代的Eden Space和Survivor Space的From Space(Survivor目前存放对象的那一块),少数情况会直接分配到老生代。当新生代的Eden Space和From Space空间不足时就会发生一次GC,进行GC后,Eden Space和From Space区的存活对象会被挪到To Space,然后将Eden Space和From Space进行清理。如果To Space无法足够存储某个对象,则将这个对象存储到老生代。在进行GC后,使用的便是Eden Space和To Space了,如此反复循环。当对象在Survivor区躲过一次GC后,其年龄就会+1。默认情况下年龄到达15的对象会被移到老生代中。

3. 典型的垃圾收集器

垃圾收集算法是垃圾收集器的理论基础,而垃圾收集器就是其具体实现。下面介绍HotSpot虚拟机提供的几种垃圾收集器。

3.1. Serial/Serial Old

最古老的收集器,是一个单线程收集器,用它进行垃圾回收时,必须暂停所有用户线程。Serial是针对新生代的收集器,采用Copying算法;而Serial Old是针对老生代的收集器,采用Mark-Compact算法。优点是简单高效,缺点是需要暂停用户线程。

3.2. ParNew

Seral/Serial Old的多线程版本,使用多个线程进行垃圾收集。

3.3. Parallel Scavenge

新生代的并行收集器,回收期间不需要暂停其他线程,采用Copying算法。该收集器与前两个收集器不同,主要为了达到一个可控的吞吐量。

3.4. Parallel Old

Parallel Scavenge的老生代版本,采用Mark-Compact算法和多线程。

3.5. CMS

Current Mark Sweep收集器是一种以最小回收时间停顿为目标的并发回收器,因而采用Mark-Sweep算法。

3.6. G1

G1(Garbage First)收集器技术的前沿成果,是面向服务端的收集器,能充分利用CPU和多核环境。是一款并行与并发收集器,它能够建立可预测的停顿时间模型。

4. 参考文章

Java垃圾回收机制

from: https://www.cnblogs.com/cielosun/p/6674431.html

Java基础:JVM垃圾回收算法相关推荐

  1. java jvm垃圾回收算法_深入理解JVM虚拟机2:JVM垃圾回收基本原理和算法

    本文转自互联网,侵删 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 喜欢的话麻烦点下Star哈 文章将同步到我的个人博客: www.how ...

  2. JVM垃圾回收算法与原理详解

    垃圾回收 参考文档 GC参考手册-Java版 理解Java的强引用.软引用.弱引用和虚引用 JVM系列(五) - JVM垃圾回收算法 如何判断对象可以回收 引用计数法 参考文章 Java JVM的引用 ...

  3. 深入理解Java虚拟机——JVM垃圾回收机制和垃圾收集器详解

    一:概述 说起垃圾回收(Garbage Collection,GC),很多人就会自然而然地把它和Java联系起来.在Java中,程序员不需要去关心内存动态分配和垃圾回收的问题,顾名思义,垃圾回收就是释 ...

  4. JVM 垃圾回收算法 -可达性分析算法!!!高频面试!!!

    前言:学习JVM,那么不可避免的要去了解JVM相关的垃圾回收算法,本文只是讲了讲了可达性分析算法,至于标记-清除.标记-复制,标记-整理,分代收集等等算法,会在近两天的文章中陆续更新出来. 很喜欢一句 ...

  5. jvm垃圾回收算法详解

    前言 相比C语言,JVM虚拟机一个优势体现在对对象的垃圾回收上,JVM有一套完整的垃圾回收算法,可以对程序运行时产生的垃圾对象进行及时的回收,以便释放JVM相应区域的内存空间,确保程序稳定高效的运行, ...

  6. JVM垃圾回收算法及垃圾回收器

    目录 一.垃圾回收GC (Garbage Collection) 1.1 垃圾回收介绍: 1.2  如何判断对象是否存活(被使用) 1.2.1 引用计数算法(已经废弃) 1.2.2 可达性分析 二.垃 ...

  7. jvm垃圾回收算法和垃圾回收器

    垃圾回收算法 jvm垃圾回收算法包括复制算法.标记清楚算法和标记整理算法,它们都基于分代收集理论.所谓分代收集理论,可以理解为jvm根据对象的生命年龄将他们分在不同的内存模块,也就是熟知的新生代和老年 ...

  8. 【深入理解java虚拟机】 - JVM垃圾回收算法

    文章目录 对象是否存活? 引用计数法 可达性分析法 强.软.弱.虚 finalize() 垃圾收集算法 分代收集理论 标记-清除算法 标记-复制算法 标记-整理算法 其他 垃圾回收算法细节实现 根节点 ...

  9. JVM垃圾回收算法 总结及汇总

    先看一眼JVM虚拟机运行时的内存模型: 1.方法区 Perm(永久代.非堆) 2.虚拟机栈 3.本地方法栈 (Native方法) 4.堆 5.程序计数器 1 首先的问题是:jvm如何知道那些对象需要回 ...

最新文章

  1. 《R语言数据挖掘》----1.12 数据集成
  2. win 2008 控制共享文件夹大小_win10如何一键网络共享
  3. android+Unity3D游戏开发之简单的物体运动
  4. jquery源码解析:jQuery数据缓存机制详解2
  5. CAN总线基础(二)——CAN总线物理层介绍(总线电压详解)
  6. 如何 打包整合linux系统文件夹 用于刷机包等等, 其中包括打包 句号开头 . 开头的文件, 排除系统文件 等...
  7. 听说你趁我不在家,欺负我老婆?
  8. 如何在Android 4.0 ICS中禁用StatusBar | SystemBar | 状态栏 【完美版】
  9. linux内存管理之uboot第一步
  10. Spark取出(Key,Value)型数据中Value值为前n条数据
  11. 【纹理映射】球面坐标、直角坐标系、纹理空间坐标系的转换
  12. “职业丑人”:大公司雇“职业杀手”大裁员
  13. pythontrun什么意思_python新手笔记一
  14. 基因编辑c语言,此“基因编辑”非彼“基因编辑”
  15. 苹果怎么清理隐藏内存?全新手机技巧,还不会的亏大了!
  16. 逻辑门电路工作原理详解
  17. 学习编程一年需要花费多少?自学可以成为程序员吗?
  18. C++基础知识整理(面试热点)
  19. 西红柿炒鸡蛋怎么做(大厨教程 教你炒出饭店的味道)
  20. html5新建一个表格,全新改良的HTML5表单建立html5新闻

热门文章

  1. UML建模——用例图(Use Case Diagram)
  2. 元宇宙iwemeta: 元宇宙与数字经济
  3. 现代信用卡管理(二)
  4. Spring JDBC-数据连接泄露解读
  5. 全局事件-广播(Broadcast)
  6. C++五子棋(六)——游戏结束
  7. java线程占用CPU_在windows下揪出java程序占用cpu很高的线程并完美解决
  8. 数据结构与算法笔记(四)—— 栈
  9. linux shell 脚本 svn自动更新项目并且打包 、发布、备份
  10. 启动mongodb服务器时发生系统错误5,CentOS 7系统下SELinux阻止MongoDB启动的问题详解...