JVM虚拟机垃圾回收(GC)算法及优缺点
一、什么是GC
GC是jvm的垃圾回收,垃圾回收的规律和原则为:
次数上频繁收集新生区(Young)
次数上较少收集养老区(Old)
基本上不动永久区(Perm)
二、GC算法(分代收集算法)
GC总共有四大算法,分别是:
①引用计数法
②复制算法(Copying)
③标记清除(Mark-Sweep)
④标记压缩(Mark-Compact)
⑤标记清除压缩(Mark-Sweep-Compact)
1.1 引用计数法
1.2 复制算法(Copying)
复制算法主要用在新生代中。
1.2.1 复制算法原理
Minor GC会把Eden中的所有活的对象都移到Survivor区域中,如果Survivor区中放不下,那么剩下的活的对象就被移到Old generation中,也即一旦收集后,Eden是就变成空的了。
当对象在 Eden ( 包括一个 Survivor 区域,这里假设是 from 区域 ) 出生后,在经过一次 Minor GC 后,如果对象还存活,并且能够被另外一块 Survivor 区域所容纳( 上面已经假设为 from 区域,这里应为 to 区域,即 to 区域有足够的内存空间来存储 Eden 和 from 区域中存活的对象 ),则使用复制算法将这些仍然还存活的对象复制到另外一块 Survivor 区域 ( 即 to 区域 ) 中,然后清理所使用过的 Eden 以及 Survivor 区域 ( 即 from 区域 ),并且将这些对象的年龄设置为1,以后对象在 Survivor 区每熬过一次 Minor GC,就将对象的年龄 + 1,当对象的年龄达到某个值时 ( 默认是 15 岁,通过-XX:MaxTenuringThreshold 来设定参数),这些对象就会成为老年代。
复制必交换,谁空谁为to
年轻代中的GC,主要是复制算法(Copying)
1.2.1 复制算法优缺点
HotSpot JVM把年轻代分为了三部分:1个Eden区和2个Survivor区(分别叫from和to)。默认比例为8:1:1。
一般情况下,新创建的对象都会被分配到Eden区(一些大对象特殊处理),这些对象经过第一次Minor GC后,如果仍然存活,将会被移到Survivor区。
对象在Survivor区中每熬过一次Minor GC,年龄就会增加1岁,当它的年龄增加到一定程度时,就会被移动到年老代中。因为年轻代中的对象基本都是朝生夕死的(90%以上),所以在年轻代的垃圾回收算法使用的是复制算法,复制算法的基本思想就是将内存分为两块,每次只用其中一块,当这一块内存用完,就将还活着的对象复制到另外一块上面。复制算法不会产生内存碎片。
复制算法它的缺点也是相当明显的。
1、它浪费了一半的内存,这太要命了。
2、如果对象的存活率很高,我们可以极端一点,假设是100%存活,那么我们需要将所有对象都复制一遍,并将所有引用地址重置一遍。复制这一工作所花费的时间,在对象存活率达到一定程度时,将会变的不可忽视。 所以从以上描述不难看出,复制算法要想使用,最起码对象的存活率要非常低才行,而且最重要的是,我们必须要克服50%内存的浪费。
1.3 标记清除(Mark-Sweep)算法
养老代一般是由标记清除或者是标记清除与标记整理的混合实现
1.3.1 标记清除算法原理
当堆中的有效内存空间(available memory)被耗尽的时候,就会停止整个程序(也被称为stop the world),然后进行两项工作,第一项则是标记,第二项则是清除。
标记:从引用根节点开始标记所有被引用的对象。标记的过程其实就是遍历所有的GC Roots,然后将所有GC Roots可达的对象标记为存活的对象。
清除:遍历整个堆,把未标记的对象清除。
缺点:此算法需要暂停整个应用,会产生内存碎片
用通俗的话解释一下标记/清除算法,就是当程序运行期间,若可以使用的内存被耗尽的时候,GC线程就会被触发并将程序暂停,随后将依旧存活的对象标记一遍,最终再将堆中所有没被标记的对象全部清除掉,接下来便让程序恢复运行。
1.3.2 标记清除算法优缺点:
- 缺点
1、首先,它的缺点就是效率比较低(递归与全堆对象遍历),而且在进行GC的时候,需要停止应用程序,这会导致用户体验非常差劲
2、其次,主要的缺点则是这种方式清理出来的空闲内存是不连续的(内存碎片),这点不难理解,我们的死亡对象都是随即的出现在内存的各个角落的,现在把它们清除之后,内存的布局自然会乱七八糟。而为了应付这一点,JVM就不得不维持一个内存的空闲列表,这又是一种开销。而且在分配数组对象的时候,寻找连续的内存空间会不太好找。
- 优点
不需要双倍的内存空间。
1.4 标记压缩(Mark-Compact)
养老代一般是由标记清除或者是标记清除与标记整理的混合实现
1.4.1 标记压缩算法原理
在整理压缩阶段,不再对标记的对象做回收,而是通过所有存活对象都向一端移动,然后直接清除边界以外的内存。
可以看到,标记的存活对象将会被整理,按照内存地址依次排列,而未被标记的内存会被清理掉。如此一来,当我们需要给新对象分配内存时,JVM只需要持有一个内存的起始地址即可,这比维护一个空闲列表显然少了许多开销。
1.4.2 标记清除算法优缺点
- 优点
**标记/整理算法不仅可以弥补标记/清除算法当中内存区域分散的缺点,也消除了复制算法当中,内存减半的高额代价**
- 缺点
标记/整理算法唯一的缺点就是效率也不高,不仅要标记所有存活对象,还要整理所有存活对象的引用地址。从效率上来说,标记/整理算法要低于复制算法。
1.5 标记清除压缩(Mark-Sweep-Compact)
1.5.1 标记清除压缩算法原理
标记清除压缩算法就是将标记清除算法与标记压缩算法结合起来。
三、总结
3.1 各个算法对比
内存效率:复制算法>标记清除算法>标记整理算法(此处的效率只是简单的对比时间复杂度,实际情况不一定如此)。
内存整齐度:复制算法=标记整理算法>标记清除算法。
内存利用率:标记整理算法=标记清除算法>复制算法。
可以看出,效率上来说,复制算法是当之无愧的老大,但是却浪费了太多内存,而为了尽量兼顾上面所提到的三个指标,标记/整理算法相对来说更平滑一些,但效率上依然不尽如人意,它比复制算法多了一个标记的阶段,又比标记/清除多了一个整理内存的过程。
所以针对不同的垃圾回收的算法的不同的特点,所以针对jvm堆中不同的区采用不同的算法,即分代收集算法。
3.2 不同分区的不同算法
- 年轻代(Young Gen)
年轻代特点是区域相对老年代较小,对象存活率低。
这种情况复制算法的回收整理,速度是最快的。复制算法的效率只和当前存活对象大小有关,因而很适用于年轻代的回收。而复制算法内存利用率不高的问题,通过hotspot中的两个survivor的设计得到缓解。
- 老年代(Tenure Gen)
老年代的特点是区域较大,对象存活率高。
这种情况,存在大量存活率高的对象,复制算法明显变得不合适。一般是由标记清除或者是标记清除与标记整理的混合实现。
Mark阶段的开销与存活对象的数量成正比,这点上说来,对于老年代,标记清除或者标记整理有一些不符,但可以通过多核/线程利用,对并发、并行的形式提标记效率。
Sweep阶段的开销与所管理区域的大小形状相关,但Sweep“就地处决”的特点,回收的过程没有对象的移动。使其相对其它有对象移动步骤的回收算法,仍然是效率最好的。但是需要解决内存碎片问题。
Compact阶段的开销与存活对象的数据成开比,如上一条所描述,对于大量对象的移动是很大开销的,做为老年代的第一选择并不合适。
基于上面的考虑,老年代一般是由**标记清除**或者是**标记清除**与 **标记整理** 的混合实现。以hotspot中的CMS回收器为例,CMS是基于Mark-Sweep实现的,对于对象的回收效率很高,而对于碎片问题,CMS采用基于Mark-Compact算法的Serial Old回收器做为补偿措施:当内存回收不佳(碎片导致的Concurrent Mode Failure时),将采用Serial Old执行Full GC以达到对老年代内存的整理。
JVM虚拟机垃圾回收(GC)算法及优缺点的更多相关文章
- JVM学习——垃圾回收GC(学习过程)
JVM学习-垃圾回收(GC) 2020年02月19日06:03:56,开始学习垃圾回收,学习资料来源(张龙老师的JVM课程) JVM内存数据区域知识复习 学习垃圾回收之前,要对JVM内部的内存区域有详 ...
- 修改Tomcat的jvm的垃圾回收GC方式为CMS
修改Tomcat的jvm的垃圾回收GC方式 cp $TOMCAT_HOME/bin/catalina.sh $TOMCAT_HOME/bin/catalina.sh.bak_20170815 vi $ ...
- 这货到底还是不是垃圾?【垃圾回收GC算法JVM篇四】
目录 1.判断对象是否存活的JVM两种计数算法 2.垃圾收集算法 3.垃圾回收算法小结 垃圾收集 Garbage Collection 通常被称为"GC", 在jvm 中,程序计数 ...
- JVM—垃圾回收GC算法
1 GC算法简介 算法 特点 标记-清除 分为"标记"和"清除"两个阶段 复制 可以解决效率问题,将可用的内存按容量划分为大小相等的两块. 标记-整理 先标记. ...
- 关于JVM的垃圾回收(GC) 这可能是你想了解的
目录 1 JVM中Java对象的分类 2 JVM的GC类型及触发条件 2.1 Young GC 2.2 Full GC 3 Java对象生成时的内存申请过程 3 Oracle JDK中的垃圾收集器 3 ...
- JVM虚拟机-垃圾回收机制与垃圾收集器概述
目录 前言 什么是垃圾回收 垃圾回收的区域 垃圾回收机制 流程 怎么判断对象已经死亡 引用计数法 可达性分析算法 不可达的对象并非一定会回收 关于引用 强引用(StrongReference) 软引用 ...
- jvm虚拟机--垃圾回收子系统
转载自cyc2018的github:https://github.com/CyC2018/Interview-Notebook/blob/master/notes/Java%20%E8%99%9A%E ...
- spark性能优化-JVM虚拟机垃圾回收调优
1 2 3 4
- JVM的垃圾回收机制 总结(垃圾收集、回收算法、垃圾回收器)
相信和小编一样的程序猿们在日常工作或面试当中经常会遇到JVM的垃圾回收问题,有没有在夜深人静的时候详细捋一捋JVM垃圾回收机制中的知识点呢?没时间捋也没关系,因为小编接下来会给你捋一捋. 一. 技术 ...
随机推荐
- Excel 冻结窗口
1.冻结前五行 鼠标选中第六行,点击视图----> 冻结窗口 ----> 冻结拆分窗口 2.冻结第一列窗口 鼠标选中第1列,点击视图----> 冻结窗口 ----> 冻结首列窗 ...
- 【整理】互联网服务端技术体系:高性能之并发(Java)
分而合之,并行不悖. 综述入口见:"互联网应用服务端的常用技术思想与机制纲要" 引子 并发,就是在同一时间段内有多个任务同时进行着.这些任务或者互不影响互不干扰,或者共同协作来完成 ...
- WEB层知识点
目录 Web 应用程序技术 HTTP 1.1 HTTP请求 1.2 HTTP响应 1.3 HTTP方法 1.4 URL 1.5 HTTP消息头 1.常用消息头 2.请求消息头 3.响应消息头 1.7 ...
- 配置简单的拦截器java中
springMVC.xml文件中==== <!-- 拦截器 --> <mvc:interceptors> <mvc:interceptor> <mvc:map ...
- 一个简单的struts2项目
1.新建一个 Dynamic Web Project 项目 2.配置 struts.xml文件 <?xml version="1.0" encoding="UTF- ...
- 微信网页授权多次回调code请求
最近在做微信网页授权的时候遇到一个问题如果直接从后台把微信授权的url参数什么的拼装好,然后直接redirect 这个url 会导致时不时的多次请求回调的url .网上说是因为网络原因,如果10s没有 ...
- VC维相关知识
假设空间H(Hypothesis Set) 输入空间D(X1...Xn) 1.增长函数(grown function) 是关于输入空间尺寸n的函数 假设空间对于D中所有实例实现分类(赋予标记)的分类方 ...
- 记录一次 Nginx 配置 proxy_pass 后 返回404问题
一. Nginx 配置 proxy_pass 后 返回404问题 故障解决和定位 1.1. 问题 在一次生产涉及多次转发的配置中, 需求是下面的图: 在配置好了 proxy_pass 之后,请求 ww ...
- Refit集成consul在asp.net core中的实践
前言 github:https://github.com/alphayu/ Refit.WebApiClient.Feign等都是支持声名式的Restful服务调用的开源组件. 这个几个组件都综合研究 ...
- 测试如何区分前后端bug
当我们测试到前后端分离的项目时,可能就会想这个bug我到底应该指给谁,是前端的问题还是后端的呢,为了让自己更专业,分清前后端问题还是很重要的. 1.如图商品详情中显示[件装:1,中包装:2 ]但是在后 ...