在之前Java 运行期数据区一文中,介绍了运行时内存的各个部分。其中程序计数器、虚拟机栈、本地方法栈都随线程消亡,所以,这几个区域的内存分配和回收都具备确定性。而 Java 堆和方法区不同,我们只有在程序运行期间才能知道会创建哪些对象,这部分的内存分配和回收都是动态的,这也正是垃圾回收器关注的部分。

对象的生与死

垃圾回收器要在进行回收前,需要确定哪些对象的状态,是“存活”还是”死亡“。

引用计数法

给对象添加一个引用计数,每当有一个地方引用对象时,引用计数加 1 ;当引用实现时,引用计数减 1 ;引用计数位 0 的对象不能再背引用。

C++ 中的 unique_ptr 内部就是通过引用计数来实现的,不过该方法有个弊端,对象间可能存在循环引用。Java 没有采取改方法。

可达性分析(Reachability Analysis)算法

Java、C# 都通过该方法来判定对象是否存活。可达性分析算法的思路是通过一系列称为“GC Roots”的对象作为起始点,从这些点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到 GC Roots 没有任何引用相连(从 GC Roots 到这个对象不可达)时,则证明这个对象是不可用的。

在 Java 中,以下几种对象可以作为 GC Roots :

  1. 虚拟机栈(栈帧中的本地变量表)中引用的对象;
  2. 方法区中类静态属性引用的对象;
  3. 方法区中常量引用的对象;
  4. 本地方法栈中 JNI(Native 方法) 引用的对象。

方法区的回收

Java 运行期数据区一文中,我们介绍过,方法区是各个线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

永久代的垃圾收集主要回收两部分内容:废弃常量无用的类。回收废弃常量与回收 Java 堆中的对象非常类似。而判定一个类是否是“无用的类”的条件则相对严苛。类需要同时满足3个条件才能算是“无用的类”:

  1. 该类所有的实例都已经被回收,也就是 Java 堆中不存在该类的任何实例。
  2. 加载该类的 ClassLoader 已经被回收;
  3. 该类对象的 java.lang.Class 对象没有在任何地方呗引用,无法在任何地方通过反射访问该类的方法。

虚拟机可以堆满足上述 3 个条件的无用类进行回收,注意,跟对象不一样,不是“无用就一定会回收”。

垃圾回收算法

标记-清除(Mark-Swipe)算法

算法氛围“标记”和“清除”两个阶段:首先标记处所有需要回收的对象,在标记完成后统一回收所有被标记的对象。该算法主要有两个不足:一是效率问题,笔记和清除两个过程的效率够不高;二是空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前出发另一次垃圾收集动作。

复制(Copying)算法

为了解决效率的问题,“复制“算法出现了,该算法将可用内存按容量氛围大小相等的两块,每次只使用其中的一块。当这一块内存用完了,就将存活着的对象复制到另一块上面,然后再把已使用过的内存空间一次清理掉。这样使得每次都是对整个半区进行回收,内存分配时久不用考虑内存碎片等复杂情况,只要一动堆顶置针,按顺序分配即可,实现简单,运行高效。该算法的缺点是内存被缩小位原来的一半。

IBM 的研究表明,新生代中的对象 98% 是“朝生夕死”的,所以并不需要按照 1:1 的比例来划分内存空间,而是将内存分为一块较大的 Eden 空间和两块较小的 Survivor 空间,每次使用 Eden 和其中一块 Survivor 。当回收时,将 Eden 和 Survivor 中还存活着的对象一次性地复制到另外一块 Survivor 空间上,最后清理掉 Eden 和 刚才用过的 Survivor 空间。

当然,我们无法保证一块 Survivor 的空间足够容纳所有的存活对象,所以需要依赖其他内存(老年代)进行分配担保(Handle Promotion)。分配担保的内容后边会介绍到。

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

根据老年代的特点,产生了“标记-整理”算法,标记过程与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,二是让所有存活的对象都向一段移动,然后直接清理掉端边界以外的内存。

分代收集(Generational Collection)算法

算法思想是:根据对象存活周期的不同将内存划分为几块。一般是把堆分为新生代和老年代,这样就可以根据各个年代的特点采用最合适的收集算法。

在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。而老年代因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记-清理”或者“标记-整理”算法来进行回收。

所有文章主要是方便自己。所以,有些地方没有特别考虑读者的感受,排版、翻译什么的,我的标准是自己看懂就行了,别打我。 如果针对文章内容有什么建议,可以在评论中回复。

Java 垃圾回收算法相关推荐

  1. go java 垃圾回收_Go/Java垃圾回收算法对比解析

    原标题:Go/Java垃圾回收算法对比解析 导读:GC 是大部分现代语言内置的特性,本文作者针对 Go 语言声称的 10ms 以下的 GC 停顿进行了深入分析,还同 Java 的垃圾收集器做了对比.G ...

  2. 6种java垃圾回收算法_被说烂了的Java垃圾回收算法,我带来了最“清新脱俗”的详细图解...

    一.概况 理解Java虚拟机垃圾回收机制的底层原理,是系统调优与线上问题排查的基础,也是一个高级Java程序员的基本功,本文就针对Java垃圾回收这一主题做一些整理与记录.Java垃圾回收器的种类繁多 ...

  3. 6种java垃圾回收算法_学习java垃圾回收

    垃圾回收(GC)一直是Java受欢迎背后的重要特性之一.垃圾回收是Java中用于释放未使用的内存的机制.本质上,它追踪所有仍在使用的对象,并将剩下的标记为垃圾.Java的垃圾回收被认为是一种自动内存管 ...

  4. 6种java垃圾回收算法_Java垃圾回收机制

    Java垃圾回收机制 说到垃圾回收(Garbage Collection,GC),很多人就会自然而然地把它和Java联系起来.在Java中,程序员不需要去关心内存动态分配和垃圾回收的问题,这一切都交给 ...

  5. Java垃圾回收算法详解

    1 概述 在前一篇文章中讲到了Java虚拟机的基础知识和运行时数据区的划分,在运行时数据区的划分中,可分为线程共享区域和线程私有区域,而Java的垃圾回收就发生在线程共享区域中,更直观的说法就是Jav ...

  6. 6种java垃圾回收算法_Java垃圾回收算法

    主要根据以下3篇博客做的整理 http://blog.csdn.net/zsuguangh/article/details/6429592 http://www.cnblogs.com/ywl925/ ...

  7. Java垃圾回收算法以及垃圾回收器

    文章目录 前言 JVM 内存区域 如何识别垃圾 引用计数法 可达性算法 虚拟机栈(栈帧中的本地变量表)中引用的对象 方法区中类静态属性引用的对象 方法区中常量引用的对象 本地方法栈中 JNI 引用的对 ...

  8. 被说烂了的Java垃圾回收算法,我带来了最“清新脱俗”的详细图解

    一.概况 理解Java虚拟机垃圾回收机制的底层原理,是系统调优与线上问题排查的基础,也是一个高级Java程序员的基本功,本文就针对Java垃圾回收这一主题做一些整理与记录.Java垃圾回收器的种类繁多 ...

  9. 内存分配算法java_被说烂了的Java垃圾回收算法,我带来了最“清新脱俗”的详细图解...

    一.概况 理解Java虚拟机垃圾回收机制的底层原理,是系统调优与线上问题排查的基础,也是一个高级Java程序员的基本功,本文就针对Java垃圾回收这一主题做一些整理与记录.Java垃圾回收器的种类繁多 ...

  10. 7张图讲透Java垃圾回收算法!学妹直呼666!!!

    JVM 在垃圾回收的时候: ① 到底使用了哪些垃圾回收算法? ② 分别在什么场景下使用? ③ 各自的优缺点? 下面就来正式的介绍下垃圾回收算法 标记-清除 标记清除是最简单和干脆的一种垃圾回收算法,他 ...

最新文章

  1. 配置动态路由协议OSPF
  2. ITK:遮罩图像的归一化相关性
  3. JavaScript~~自调用方法
  4. python中@staticmethod_Python中的@staticmethod和@classmethod的区别
  5. java的static类_java中staticclass静态类详解
  6. 如何利用wordpress搭建自己独立的博客(个人网站)
  7. eclipse import的项目报autowired cannot be resolved to a type的错误
  8. Function.prototype.bind、call与apply方法简介
  9. Could not find a version that satisfies the requirement PyQt5-Qt5>=5.15.2 (from pyqt5) (from version
  10. 穿山甲(巨量引擎)广告接入
  11. 一文看懂什么是文本挖掘
  12. connection reset by peer
  13. 在 Windows 系统下,如何将“使用VSCode打开”添加至鼠标右键菜单栏
  14. 浏览器报错‘‘styleSheets undefined‘‘
  15. 安卓实现仿微信点赞好友昵称列表,中间用逗号隔开
  16. SpringBoot导出pdf文件学习
  17. 2021年N1叉车司机模拟考试及N1叉车司机证考试
  18. 准到吓人的手相。。。
  19. 用 Jester 对测试进行测试
  20. linux bzip2压缩文件,bzip2命令_Linux bzip2命令:压缩和解压文件(.bz2文件)

热门文章

  1. DTCMS添加栏目教程
  2. 小程序点击图片查看详情
  3. 计算机配件对比,基本参数 尺寸对比 接口对比
  4. 计算机二十四点游戏怎么玩,扑克牌二十四点怎么玩?扑克牌二十四点游戏规则介绍...
  5. 如何让bootbox弹框垂直居中
  6. Oracle数据库常用的管理工具介绍
  7. freeradius 3.0 mysql_求助FreeRadius+MySql 配置
  8. 根据出库、入库表,实现对库存的信息查询
  9. Java毕设项目大学生旅游拼团网站计算机(附源码+系统+数据库+LW)
  10. inssider序列号_inSSIDer v4.2.1.109完美注册版