GC 算法与种类

 对于垃圾收集(GC), 我们需要考虑三件事情:哪些内存需要回收?如何判断是垃圾对象?垃圾回收算法有哪些?

一、GC的工作区域

1、不是GC的工作区域

    (1)程序计数器、虚拟机栈和本地方法栈三个区域是线程私有的,随线程生而生,随线程灭而灭;

    (2)栈中的栈帧随着方法的进入和退出而进行入栈和出栈操作,每个栈帧中分配多少内存基本上是在类结构确定下来时就已知的,因此这几个区域的内存分配和回收都具有确定性。

在这几个区域不需要过多考虑回收的问题,因为方法结束或线程结束时,内存自然就跟随着回收了。

2、GC的工作区域(哪些内存需要GC回收?)

(1)垃圾回收重点关注的是堆和方法区部分的内存。

       因为一个接口中的多个实现类需要的内存可能不一样,一个方法的多个分支需要的内存也可能不一样,我们只有在程序处于运行期间才能知道会创建哪些对象,这部分内存的分

配和回收都是动态的,所以垃圾回收器所关注的主要是这部分的内存。

二、垃圾对象的判定

Java堆中存放着几乎所有的对象实例,垃圾收集器对堆中的对象进行回收前,要先确定这些对象是否还有用,哪些还活着。对象死去的时候才需要回收。

1、引用计数法

      引用计数法的逻辑是:在堆中存储对象时,在对象头处维护一个counter计数器,如果一个对象增加了一个引用与之相连,则将counter++。

如果一个引用关系失效则counter–。如果一个对象的counter变为0,则说明该对象已经被废弃,不处于存活状态。

优点

    1)可即刻回收垃圾,每个对象都知道自己的被引用数,当counter为0时,对象就会把自己作为空闲空间连接到空闲链表,也就是在对象变成垃圾的同时就会被回收.

    2)最大暂停时间短,每次通过指向mutator生成垃圾时,这部分垃圾都会被回收,大幅削减了mutator的最大暂停时间。

缺点

    1)引用和去引用伴随加法和减法,影响性能

    2)很难处理循环引用

2、可达性分析算法

      这种算法的基本思路是通过一系列名为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,就证明此对象是不可用的。

Java语言是通过可达性分析算法来判断对象是否存活的。

在Java语言里,可作为GC Roots的对象包括下面几种:

      (1)虚拟机栈(栈帧中的本地变量表)中引用的对象。

      (2)方法区中的类静态属性引用的对象。

      (3)方法区中的常量引用的对象。

      (4)本地方法栈中JNI(Native方法)的引用对象。

 三、垃圾回收算法

1、标记-清除算法

简单来说有两个步骤:标记、清除。

  (1). 标记阶段:找到所有可访问的对象,做个标记

  (2). 清除阶段:遍历堆,把未被标记的对象回收

 缺  点

   (1)因为涉及大量的内存遍历工作,所以执行性能较低,这也会导致“stop the world”时间较长,java程序吞吐量降低;

   (2)对象被清除之后,被清除的对象留下内存的空缺位置会造成内存不连续,空间浪费。

2、标记整理(压缩)算法 

标记-整理算法适合用于存活对象较多的场合,如老年代。它在标记-清除算法的基础上做了一些优化。

     (1)、标记阶段:它的第一个阶段与标记/清除算法是一模一样的。

     (2)、整理阶段:移动所有存活的对象,且按照内存地址次序依次排列,然后将末端内存地址以后的内存全部回收。

       上图中可以看到,标记的存活对象将会被整理,按照内存地址依次排列,而未被标记的内存会被清理掉。如此一来,当我们需要给新对象分配内存时,JVM只需要持有一个内存的起始地址即可,这比维护一个空闲

列表显然少了许多开销。

优点

      标记/整理算法不仅可以弥补标记/清除算法当中,内存区域分散的缺点,也消除了复制算法当中,内存减半的高额代价。

缺点

     标记/整理算法唯一的缺点就是效率也不高。不仅要标记所有存活对象,还要整理所有存活对象的引用地址。从效率上来说,标记/整理算法要低于复制算法。 

3、复制算法

      复制算法简单来说就是把内存一分为二,但只使用其中一份,在垃圾回收时,将正在使用的那份内存中存活的对象复制到另一份空白的内存中,最后将正在使用的内存空间的对象清除,完成垃圾回收。

优点
       复制算法使得每次都只对整个半区进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况,只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效。
缺点
       复制算法的代价是将内存缩小为原来的一半,这个太要命了。

注意(重要)

       现在的虚拟机使用复制算法来进行新生代的内存回收。因为在新生代中绝大多数的对象都是“朝生夕亡”,所以不需要将整个内存分为两个部分,而是分为三个部分,一块为Eden(伊面区)和两块较小的

Survivor(幸存区)空间(默认比例->8:1:1)。每次使用Eden和其中的一块Survivor,垃圾回收时候将上述两块中存活的对象复制到另外一块Survivor上,同时清理上述Eden和Survivor。所以每次新生代就可以使用90%

的内存。只有10%的内存是浪费的。(不能保证每次新生代都少于10%的对象存活,当在垃圾回收复制时候如果一块Survivor不够时候,需要老年代来分担,大对象直接进入老年代) 

总的来讲:复制算法不适用于存活对象较多的场合,如老年代(复制算法适合做新生代的GC)

 4、三种算法总结

相同点

      (1)三个算法都基于根搜索算法去判断一个对象是否应该被回收,而支撑根搜索算法可以正常工作的理论依据,就是语法中变量作用域的相关内容。

      (2)在GC线程开启时,或者说GC过程开始时,它们都要暂停应用程序(stop the world)。

区别

三种算法比较:

       效率:复制算法>标记-整理算法>标记-清除算法;

       内存整齐度:复制算法=标记-整理算法>标记-清除算法

       内存利用率:标记-整理算法=标记-清除算法>复制算法

 5、分代收集算法

      首先这不是一种新算法,它是一种思想。现在使用的Java虚拟机并不是只是使用一种内存回收机制,而是分代收集的算法。就是将内存根据对象存活的周期划分为几块。一般是把堆分为新生代、和老年代。短命对

象存放在新生代中,长命对象放在老年代中。

    这个图是我拷贝来的,但要记住java8以后,已经没有永久区了,之前永久区存放的东西基本上放到了元空间中。

对于不同的代,采用不同的收集算法:

       新生代:由于存活的对象相对比较少,因此可以采用复制算法该算法效率比较快。

       老年代:由于存活的对象比较多哈,可以采用标记-清除算法或是标记-整理算法。

参考

   1、Java垃圾回收(GC)机制详解

   2、深入理解JVM:Java垃圾收集

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/130293.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机视觉领域经典模型汇总(2023.09.08

一、RCNN系列 1、RCNN RCNN是用于目标检测的经典方法,其核心思想是将目标检测任务分解为两个主要步骤:候选区域生成和目标分类。 候选区域生成:RCNN的第一步是生成可能包含目标的候选区域,RCNN使用传统的计算机视觉技术&#x…

1905. 统计子岛屿

给你两个 m x n 的二进制矩阵 grid1 和 grid2 ,它们只包含 0 (表示水域)和 1 (表示陆地)。一个 岛屿 是由 四个方向 (水平或者竖直)上相邻的 1 组成的区域。任何矩阵以外的区域都视为水域。 如…

记录第一次带后端团队

在过去的一个半月里我第一次作为后端开发组长角色参与公司项目从0到1的开发,记录这一次开发的经历。 1、背景介绍 首先说明一下背景。我所在的公司是做智慧社区相关业务,开发的项目是系统升级工具,方便公司实施同事安装和升级系统。 参与后…

借助ChatGPT使用Pandas实现Excel数据汇总

一、问题的提出 现在有如下一个Excel表: 上述Excel表中8万多条数据,记录的都是三年以来花菜类的销量,现在要求按月汇总实现统计每个月花菜类的销量总和,如果使用Python的话要给出代码。 二、问题的解决 1.首先可以用透视表的方…

冒泡排序、选择排序、插入排序、希尔排序

冒泡排序 基本思想 代码实现 # 冒泡排序 def bubble_sort(arr):length len(arr) - 1for i in range(length):flag Truefor j in range(length - i):if arr[j] > arr[j 1]:temp arr[j]arr[j] arr[j 1]arr[j 1] tempflag Falseprint(f第{i 1}趟的排序结果为&#…

ElasticSearch入门

一、基本命令_cat 1、查看节点信息 http://192.168.101.132:9200/_cat/nodes2、查看健康状况 http://192.168.101.132:9200/_cat/health3、查看主节点的信息 http://192.168.101.132:9200/_cat/master4、查看所有索引 http://192.168.101.132:9200/_cat/indices二、索引一…

思科的简易配置

vlan 划分配置 1. 拓扑连接 2. 终端设备配置,vlan(v2, v3)配置,模式设置 然后设置交换机 fa 0/5 口为 trunk 模式,使得不同交换机同一 vlan 下 PC 可以互连 3.测试配置结果 用 ip 地址为 192.168.1.1 的主机(PC0)向同一 vlan(v2)下的 192.…

PN结解释

基本原理 PN结由P和N组成 硅掺杂硼,缺少电子,显正电,就是P(Positive) 硅掺杂磷,多出电子,显负电,就是N(Negative) 将P和N拼接 左边代表游离的电子&#xf…

想要精通算法和SQL的成长之路 - 课程表II

想要精通算法和SQL的成长之路 - 课程表 前言一. 课程表II (拓扑排序)1.1 拓扑排序1.2 题解 前言 想要精通算法和SQL的成长之路 - 系列导航 一. 课程表II (拓扑排序) 原题链接 1.1 拓扑排序 核心知识: 拓扑排序是专…

AI是风口还是泡沫?

KlipC报道:狂热的人工智能追捧潮有所冷静,投资者在“上头”的追涨之后,开始回归到对基本面的关注。 KlipC的合伙人Andi D表示:“近日,有关英伟达二季度“破纪录”财报涉嫌造假的话题正在社交媒体和投资者论坛中甚嚣尘上…

XShell7 + Xftp7 + IDEA 打包MapReduce程序到集群运行

参考博客 【MapReduce打包成jar上传到集群运行】http://t.csdn.cn/2gK1d 【Xshell7/Xftp7 解决强制更新问题】http://t.csdn.cn/rxiBG IDEA打包MapReduce程序 这里的打包是打包整个项目,后期等学会怎么打包单个指定的mapreduce程序再来更新博客。 1、编译打包 …

vscode 画流程图

文章目录 1、安装插件 draw2、新建文件3、开始画图4、另存为图片 vscode可以画流程图了,只需要安装插件就可以了。 1、安装插件 draw 2、新建文件 3、开始画图 4、另存为图片

Linux编辑器vim

目录 一、vim的几种模式 1、命令模式 2、编辑/插入模式 3、底行模式 ①增加行号 ②分屏操作 ③不退出vim执行命令 4、替换模式 二、vim的常见命令 1、yy命令 2、p命令 3、dd命令 4、u命令 5、Ctrl r命令 6、shirtg命令 7、gg命令 8、shirt6命令 9、shirt4命…

(其他) 剑指 Offer 61. 扑克牌中的顺子 ——【Leetcode每日一题】

❓剑指 Offer 61. 扑克牌中的顺子 难度:简单 从若干副扑克牌中随机抽 5 张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大…

Qt应用开发(基础篇)——组合框容器 QGroupBox

一、前言 QGroupBox继承于QWidget,是一个带有标题的组合框架容器控件。 QGroupBox组合框容器自带一个顶部标题,一个面板。面板内部展示各种各样的部件,标题用来解释这些部件为什么集合在一起,并且支持键盘快捷方式切换部件焦点。比…

Android逆向——脱壳解析

“壳”是一种对程序进行加密的程序,“壳”形象地表现了这个功能。我们可以把被加壳的程序当成食物,而加壳程序就是在外面加上一层坚硬的外壳,防止别人去窃取其中的程序。加壳后的程序依然可以被直接运行。在程序运行时壳的代码先运行&#xf…

【C++】怎么接受未知数量的参数?

2023年9月8日,周五下午 目录 第一种方式:可变参数函数(Variadic Function)头文件使用方法详解va_start宏详解va_arg宏示例程序 第一种方式:可变参数函数(Variadic Function) 可变参数函数(Variadic Function)是一种可以接受不定数量参数的函…

静态代理和动态代理笔记

总体分为: 1.静态代理: 代理类和被代理类需要实现同一个接口.在代理类中初始化被代理类对象.在代理类的方法中调 用被代理类的方法.可以选择性的在该方法执行前后增加功能或者控制访问 2.动态代理: 在程序执行过程中,实用JDK的反射机制,创建代理对象,并动态的指定要…

STM32-HAL库07-软件SPI驱动0.96寸OLED

STM32-HAL库07-软件SPI驱动0.96寸OLED 一、所用材料: STM32VGT6自制控制板 STM32CUBEMX(HAL库软件) MDK5 二、所学内容: 通过HAL库配置四个GPIO输出口,对其进行软件模拟SPI发送规则,进而驱动OLED进行数…

C#__文件操作之FileInfo和DirectoryInfo

// 代码(含注释) class Program{static void Main(string[] args){// FileInfo 文件操作FileInfo myFile new FileInfo("D:\C#编程\文件操作之FileInfo和DirectoryInfo\TextFile1.txt");// 实例方法// myFile.CopyTo("D:\C#编程\文件操作…