一.垃圾回收的基本概念

垃圾回收(GC,Garbage Collection),指内存中不会再被使用的对象清理掉。

垃圾回收有很多种算法:如引用计数法、标记压缩法、复制算法、分代/分区的思想

二.垃圾回收算法

1.引用计数法:这是个比较古老而经典的垃圾收集算法,其核心就是在对象被其他所引用时计数器+1,当应用时效时则-1,但是这种方式有非常严重的问题:无法处理循环引用的情况。还有就是每次进行+-操作比较浪费系统的性能

2.标记清除法:就是分为标记和清除两个阶段进行处理内存中的对象。这种方式也有非常大的弊端,就是空间碎片问题。垃圾回收后的空间不是连续的,不连续的内存空间的工作效率要低于连续的内存空间

原理:对于“活”的对象,一定可以追溯到其存活在堆栈、静态存储区之中的引用。这个引用链条可能会穿过数个对象层次。第一阶段:从GC roots开始遍历所有的引用,对有活的对象进行标记。第二阶段:对堆进行遍历,把未标记的对象进行清除。这个解决了循环引用的问题。

3.复制算法:其核心思想就是将内存空间划分为两块,每次只使用其中一块,在垃圾回收时,将正在使用的内存中的存留对象复制到未被使用的内存块中去,之后去清除之前正在使用的内存块中所有的对象,反复去交换两个内存的角色,完成垃圾收集。(java新生代里的s0和s1空间就是使用这种算法)

4.标记压缩法:标记压缩分在标记清除法的基础上做了优化,把存活的对象压缩到内存的一端,然后进行垃圾清理(老年代使用的就是这种算法)

ps:新生代和老年代采用不同GC算法的原因

先说新生代,因为新生代的对象是很不稳定的,被回收的概率达到80%,所以一个对象基本是被回收的,这个时候如果采用标记压缩法,会导致大量的空间被压缩;而采用复制算法,只有少数的对象会在s0/s1区中做转换

再说说老年代,老年代的对象是经过多次GC算法的回收之后留下来的,非常稳定,这时如果采用复制算法,将消耗大量的空间,并且很多是无谓的复制;而采用标记压缩法,因为对象很稳定,所以压缩的对象其实很少

5.分区算法

jvm把内存分成一个个的小片,每个小片里单独进行GC,目的是为了较少GC的停顿时间

该算法是jdk1.7以后提出 来的,应用不广泛

三.GC停顿

垃圾回收器的任务是识别和回收垃圾对象进行内存清理,为了让垃圾回收器可以高效执行,大部分情况下,会要求系统进入一个停顿状态,停顿的目的是终止所有线程,只有这样系统才会没有新的垃圾产生,同时停顿保证了系统状态在某一瞬间的一致性,也有益于更好地标记垃圾对象。

四.垃圾收集器的种类

1.串行垃圾回收器

单线程进行垃圾回收,对于并行能力弱的计算机来说,串行垃圾回收器的专注性和独占性往往有更好的性能提现。

2.并行垃圾回收器

并行回收器在串行的基础上做了改进,可以使用多个线程同时进行垃圾回收,对云计算能力强的计算机而言,可以有效缩短垃圾回收所需要的实际时间

(1)ParNew回收器

ParNew回收器是一个工作在新生代的垃圾收集器,它只是简单地将串行收集器多线程化,回收策略和算法跟串行回收器一样

(2)ParallelGC回收器

新生代ParallelGC回收器,使用了复制算法的收集器,也是多线程独占形式的收集器,但是ParallelGC回收器有个非常重要的特点,它非常关注系统的吞吐量

(3)ParallelOldGC回收器

与ParallelGC相似,但是其工作空间在老年代

3.CMS(Concurrent Mark Sweep)回收器(主流)

并发标记清除,使用的是标记清除法,主要关注系统停顿的时间

CMS并不是独占的回收器,也就是说,CMS在回收的过程中,程序仍然在不停地工作,又有新的垃圾不断产生,所以在使用CMS过程中应该确保应用程序的内存足够可用。CMS不会等到应用程序饱和时采取回收垃圾,而是到达一定的阀值时就开始回收了,默认是68(阀值可以配置),也就是说,当老年代空间使用率打到68的时候,会执行CMS回收。如果内存使用率增长的很快,在CMS执行过程中就已经出现了内存不足的情况,此时CMS回收就会失败,jvm将启动老年代串行回收器进行垃圾回收,这会导致应用程序中断,直到垃圾回收完成后才会正常工作,这个过程GC的停顿时间可能较长。

标记清除法有个问题是碎片问题,CMS有个参数可以设定多少次CMS垃圾回收之后进行一次压缩

4.G1回收器

jdk1.7中提出,从长期目标来看是取代CMS回收器的。G1属于分代垃圾回收器,区分新生代和老年代,依然有eden和from/to区,不要求整个eden区或者新生代/老年代都空间连续,它使用了分区算法

并行性:G1回收期间可以多线程同时工作

并发性:G1拥有与应用程序交替执行的能力,部分工作可以与应用程序同时执行,在整个GC期间不会完全阻塞应用程序

分代GC:G1依然是个分代的收集器,但是它兼顾新生代和老年代一起工作,之前的垃圾收集器他们或在新生代工作,或在老年代工作,因此这是个很大的不同。

空间整理:G1回收的过程中,不会像CMS那样在若干次GC之后需要进行碎片整理。G1采用了有效复制对象的方式,减少空间碎片

可预见性:由于分区的原因,G1可以只选取部分区域进行回收,缩小了回收范围,提升了性能

JVM——GC(垃圾回收)算法的更多相关文章

  1. JVM(九):垃圾回收算法

    JVM(九):垃圾回收算法 在本文中,我们将从概念模型的角度探讨 JVM 是如何回收对象,包括 JVM 是如何判断一个对象已经死亡,什么时候在哪里进行了垃圾回收,垃圾回收有几种核心算法,每个算法优劣是 ...

  2. JVM G1垃圾回收算法简要介绍

    JVM G1垃圾回收算法简要介绍 G1的特点 能够像CMS垃圾回收算法一样并发操作应用线程(潜台词:多核) 无需太长时间即可压缩空闲内存空间(潜台词:不会引起太多的GC停顿时间) 尽可能地让GC时长可 ...

  3. jvm详情——3、JVM基本垃圾回收算法回收策略

    JVM基本垃圾回收算法回收策略 引用计数(Reference Counting):比较古老的回收算法.原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数.垃圾回收时,只用收集计数为0的 ...

  4. JVM常见垃圾回收算法

    jdk1.7.0_79 众所周知,Java是一门不用程序员手动管理内存的语言,全靠JVM自动管理内存,既然是自动管理,那必然有一个垃圾内存的回收机制或者回收算法.本文将介绍几种常见的垃圾回收(下文简称 ...

  5. jvm的垃圾回收算法

    一.对象存活判断判断对象是否存活一般有两种方式:1.引用计数:每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时可以回收.此方法简单,无法解决对象相互循环引用的问题.2 ...

  6. Java GC 垃圾回收算法 内存分配

    垃圾回收(Garbage Collection, GC)是Java不同于c与c++的重要特性之一. 他帮助Java自动清空堆中不再使用的对象. 由于不需要手动释放内存,程序员在编程中也可以减少犯错的机 ...

  7. 深入理解JVM一垃圾回收算法

    我们都知道java语言与C语言最大的区别就是内存自动回收,那么JVM是怎么控制内存回收的,这篇文章将介绍JVM垃圾回收的几种算法,从而了解内存回收的基本原理. 一.stop the world 在介绍 ...

  8. jvm学习-垃圾回收算法(三)

     垃圾回收算法  引用计数法 比较古老的一种垃圾回收算法.在java的GC并没有采用 增加一个引用 引用+1 减少一个引用引用减一 每次清除引用为0的的对象 缺点:不能回收循环引用的垃圾对象 标记清除 ...

  9. Java学习之二(线程(了解) JVM GC 垃圾回收)

    线程与进程(了解)→JVM→字节码→GC 一.程序 = 算法 + 数据结构(大佬) 二.程序 = 框架 + 业务逻辑(现实) 1.线程与进程.同步与异步 1.1进程是什么? 进程就是操作系统控制的基本 ...

  10. 深入探究JVM之垃圾回收算法实现细节

    @ 目录 前言 垃圾回收算法实现细节 根节点枚举 安全点 安全区域 记忆集和卡表 写屏障 并发的可达性分析 低延迟GC Shenandoah ZGC 总结 前言 本篇紧接上文,主要讲解垃圾回收算法的实 ...

随机推荐

  1. moviepy音视频剪辑:moviepy中的剪辑相关类及关系

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt+moviepy音视频剪辑实战 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 y在 ...

  2. PyQt(Python+Qt)学习随笔:QListWidget的信号简介

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 不含继承信号,QListWidget自身的信号包括如下: currentItemChanged(QL ...

  3. PyQt(Python+Qt)学习随笔:gridLayout的layoutRowMinimumHeight和layoutColumnMinimumWidth属性

    Qt Designer中网格布局(gridLayout)中,layoutRowMinimumHeight和layoutColumnMinimumWidth两个属性分别设置网格布局中各行的最小高度和各列 ...

  4. Typescript + React 高仿 Antd 从零到一打造自己的组件库(完整)

    买了张轩老师的课程,感觉很不错,适用于高级进阶,老师讲的通俗易懂,欢迎讨论学习.WX:Jujiu_i

  5. print(end="\r") 滚动输出到屏幕

    for i in range(10000): print(i, end = "\r") print(end="\r") 滚动输出到屏幕

  6. 第 5篇 Scrum 冲刺博客

    一.站立式会议 1.站立式会议照片 2.昨天已完成的工作 售货员页面功能 3.今天计划完成的工作 添加登录系统账号密码数据库模块 继续对商品销售部分进行编码 职工管理页面 4.工作中遇到的困难 ①页面 ...

  7. CCF统一省选 Day2 题解

    此题解是教练给我的作业,AK了本场比赛的人,以及认为题目简单的人可以不必看 T1 算法一 暴力枚举对信号站顺序的不同排列,然后对代价取\(\min\)即可. 时间复杂度\(O(m! \cdot n)\ ...

  8. 链判断运算符和Null 判断运算符

    链判断运算符 如果我们要获取一个对象的深层嵌套属性,例如获取文章标题res.data.article.title,然后为了安全起见,我们肯定不能直接这样获取,万一res对象没有article属性了呢, ...

  9. 微信小程序图片上传和裁剪

    本篇博客用于解决微信小程序图片裁剪问题 图片裁剪常用于头像选择和图片合成等. 图片裁剪解决方案: 目前网络上知名的微信小程序图片裁剪插件是we-cropper(文末有链接) 操作步骤:下载好we-cr ...

  10. double类型和int类型的区别

    引例: double a=19*3.3; System.out.print(a); 结果为62.9999996,不是62.7:这里不单纯是因为给的是double类型 (1) 62.7 和 62.699 ...