JVM垃圾回收算法
1.标记清除(Mark-Sweep)
原理:
从根集合节点进行扫描,标记出所有的存活对象,最后扫描整个内存空间并清除没有标记的对象(即死亡对象)适用场合:
存活对象较多的情况下比较高效适用于年老代(即旧生代)
缺点:
标记清除算法带来的一个问题是会存在大量的空间碎片,因为回收后的空间是不连续的,这样给大对象分配内存的时候可能会提前触发full gc。
2.复制算法(Copying)
原理:
从根集合节点进行扫描,标记出所有的存活对象,并将这些存活的对象复制到一块儿新的内存(图中下边的那一块儿内存)上去,之后将原来的那一块儿内存(图中上边的那一块儿内存)全部回收掉。
适用场合:存活对象较少的情况下比较高效扫描了整个空间一次(标记存活对象并复制移动)适用于年轻代(即新生代):基本上98%的对象是”朝生夕死”的,存活下来的会很少
缺点:需要一块儿空的内存空间需要复制移动对象(可使用空间减少)
3.标记整理(Mark-Compact)
原理:
从根集合节点进行扫描,标记出所有的存活对象,最后扫描整个内存空间并清除没有标记的对象(即死亡对象)(可以发现前边这些就是标记-清除算法的原理),清除完之后,将所有的存活对象左移到一起。
适用场合:
用于年老代(即旧生代)
缺点:
需要移动对象,若对象非常多而且标记回收后的内存非常不完整,可能移动这个动作也会耗费一定时间扫描了整个空间两次(第一次:标记存活对象;第二次:清除没有标记的对象)
优点:
不会产生内存碎片
4.增量算法
增量算法的基本思想是,如果一次性将所有的垃圾进行处理,需要造成系统长时间的停顿,那么就可以让垃圾收集线程和应用程序线程交替执行。每次,垃圾收集线程只收集一小片区域的内存空间,接着切换到应用程序线程。依次反复,直到垃圾收集完成。
优点:
使用这种方式,由于在垃圾回收过程中,间断性地还执行了应用程序代码,所以能减少系统的停顿时间。
缺点:
因为线程切换和上下文转换的消耗,会使得垃圾回收的总体成本上升,造成系统吞吐量的下降。
垃圾回收器
1.Serial/Serial Old收集器
Serial收集器是最古老的收集器,它的缺点是当Serial收集器想进行垃圾回收的时候,必须暂停用户的所有进程,即stop the world。到现在为止,它依然是虚拟机运行在client模式下的默认新生代收集器,与其他收集器相比,对于限定在单个CPU的运行环境来说,Serial收集器由于没有线程交互的开销,专心做垃圾回收自然可以获得最高的单线程收集效率。
2.ParNew收集器
ParNew收集器是Serial收集器新生代的多线程实现,注意在进行垃圾回收的时候依然会stop the world,只是相比较Serial收集器而言它会运行多条进程进行垃圾回收。
ParNew收集器在单CPU的环境中绝对不会有比Serial收集器更好的效果,甚至由于存在线程交互的开销,该收集器在通过超线程技术实现的两个CPU的环境中都不能百分之百的保证能超越Serial收集器。当然,随着可以使用的CPU的数量增加,它对于GC时系统资源的利用还是很有好处的。它默认开启的收集线程数与CPU的数量相同,在CPU非常多(譬如32个,现在CPU动辄4核加超线程,服务器超过32个逻辑CPU的情况越来越多了)的环境下,可以使用-XX:ParallelGCThreads参数来限制垃圾收集的线程数。
3.Parallel Scavenge收集器
Parallel是采用复制算法的多线程新生代垃圾回收器,似乎和ParNew收集器有很多的相似的地方。但是Parallel Scanvenge收集器的一个特点是它所关注的目标是吞吐量(Throughput)。所谓吞吐量就是CPU用于运行用户代码的时间与CPU总消耗时间的比值,即吞吐量=运行用户代码时间 / (运行用户代码时间 + 垃圾收集时间)。停顿时间越短就越适合需要与用户交互的程序,良好的响应速度能够提升用户的体验;而高吞吐量则可以最高效率地利用CPU时间,尽快地完成程序的运算任务,主要适合在后台运算而不需要太多交互的任务。
4.CMS收集器
CMS(Concurrent Mark Sweep)收集器是一个比较重要的回收器,现在应用非常广泛,我们重点来看一下,CMS一种获取最短回收停顿时间为目标的收集器,这使得它很适合用于和用户交互的业务。从名字(Mark Sweep)就可以看出,CMS收集器是基于标记清除算法实现的。它的收集过程分为四个步骤:
初始标记(initial mark)并发标记(concurrent mark)重新标记(remark)并发清除(concurrent sweep)注意初始标记和重新标记还是会stop the world,但是在耗费时间更长的并发标记和并发清除两个阶段都可以和用户进程同时工作。
不过由于CMS收集器是基于标记清除算法实现的,会导致有大量的空间碎片产生,在为大对象分配内存的时候,往往会出现老年代还有很大的空间剩余,但是无法找到足够大的连续空间来分配当前对象,不得不提前开启一次Full GC。
为了解决这个问题,CMS收集器默认提供了一个-XX:+UseCMSCompactAtFullCollection收集开关参数(默认就是开启的),用于在CMS收集器进行FullGC完开启内存碎片的合并整理过程,内存整理的过程是无法并发的,这样内存碎片问题倒是没有了,不过停顿时间不得不变长。虚拟机设计者还提供了另外一个参数-XX:CMSFullGCsBeforeCompaction参数用于设置执行多少次不压缩的FULL GC后跟着来一次带压缩的(默认值为0,表示每次进入Full GC时都进行碎片整理)。
不幸的是,它作为老年代的收集器,却无法与jdk1.4中已经存在的新生代收集器Parallel Scavenge配合工作,所以在jdk1.5中使用cms来收集老年代的时候,新生代只能选择ParNew或Serial收集器中的一个。ParNew收集器是使用-XX:+UseConcMarkSweepGC选项启用CMS收集器之后的默认新生代收集器,也可以使用-XX:+UseParNewGC选项来强制指定它。
5.G1收集器
G1收集器是一款面向服务端应用的垃圾收集器。HotSpot团队赋予它的使命是在未来替换掉JDK1.5中发布的CMS收集器。与其他GC收集器相比,G1具备如下特点:
并行与并发:
G1能更充分的利用CPU,多核环境下的硬件优势来缩短stop the world的停顿时间。
分代收集:和其他收集器一样,分代的概念在G1中依然存在,不过G1不需要其他的垃圾回收器的配合就可以独自管理整个GC堆。
空间整合:G1收集器有利于程序长时间运行,分配大对象时不会无法得到连续的空间而提前触发一次GC。可预测的非停顿:这是G1相对于CMS的另一大优势,降低停顿时间是G1和CMS共同的关注点,能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒。在使用G1收集器时,Java堆的内存布局和其他收集器有很大的差别,它将这个Java堆分为多个大小相等的独立区域,虽然还保留新生代和老年代的概念,但是新生代和老年代不再是物理隔离的了,它们都是一部分Region(不需要连续)的集合。
虽然G1看起来有很多优点,实际上CMS还是主流。
与GC相关的常用参数
除了上面提及的一些参数,下面补充一些和GC相关的常用参数:
-Xmx: 设置堆内存的最大值。
-Xms: 设置堆内存的初始值。
-Xmn: 设置新生代的大小。
-Xss: 设置栈的大小。
-PretenureSizeThreshold: 直接晋升到老年代的对象大小,设置这个参数后,大于这个参数的对象将直接在老年代分配。
-MaxTenuringThrehold: 晋升到老年代的对象年龄。每个对象在坚持过一次Minor GC之后,年龄就会加1,当超过这个参数值时就进入老年代。
-UseAdaptiveSizePolicy: 在这种模式下,新生代的大小、eden 和 survivor 的比例、晋升老年代的对象年龄等参数会被自动调整,以达到在堆大小、吞吐量和停顿时间之间的平衡点。在手工调优比较困难的场合,可以直接使用这种自适应的方式,仅指定虚拟机的最大堆、目标的吞吐量 (GCTimeRatio) 和停顿时间 (MaxGCPauseMills),让虚拟机自己完成调优工作。
-SurvivorRattio: 新生代Eden区域与Survivor区域的容量比值,默认为8,代表Eden: Suvivor= 8: 1。
-XX:ParallelGCThreads:设置用于垃圾回收的线程数。通常情况下可以和 CPU 数量相等。但在 CPU 数量比较多的情况下,设置相对较小的数值也是合理的。
-XX:MaxGCPauseMills:设置最大垃圾收集停顿时间。它的值是一个大于 0 的整数。收集器在工作时,会调整 Java 堆大小或者其他一些参数,尽可能地把停顿时间控制在 MaxGCPauseMills 以内。
-XX:GCTimeRatio:设置吞吐量大小,它的值是一个 0-100 之间的整数。假设 GCTimeRatio 的值为 n,那么系统将花费不超过 1/(1+n) 的时间用于垃圾收集。
本文转自《阿里P8架构师谈JVM的内存分配、运行原理、回收算法机制》
- 从C#垃圾回收(GC)机制中挖掘性能优化方案
GC,Garbage Collect,中文意思就是垃圾回收,指的是系统中的内存的分配和回收管理.其对系统性能的影响是不可小觑的.今天就来说一下关于GC优化的东西,这里并不着重说概念和理论,主要说一些实 ...
- 性能测试三十五:jvm垃圾回收-GC
垃圾回收-GC 三个问题 哪些内存需要回收? 什么时候回收? 如何回收? YoungGC和FullGC: 新生代引发的GC叫YoungGC 老年代引发的GC叫FullGC FullGC会引起整个Jvm ...
- java JVM垃圾回收机制
Java语言出来之前,大家都在拼命的写C或者C++的程序,而此时存在一个很大的矛盾,C++等语言创建对象要不断的去开辟空间,不用的时候有需要不断的去释放控件,既要写构造函数,又要写析构函数,很多时候都 ...
- [JVM-3]Java垃圾回收(GC)机制和垃圾收集器选择
哪些内存需要回收? 1.引用计数法 这个算法的实现是,给对象中添加一个引用计数器,每当一个地方引用这个对象时,计数器值+1:当引用失效时,计数器值-1.任何时刻计数值为0的对象就是不可能再被使用的.这 ...
- JVM 垃圾回收GC Roots Tracing
1.跟搜索算法: JVM中对内存进行回收时,需要判断对象是否仍在使用中,可以通过GC Roots Tracing辨别. 定义: 通过一系列名为”GCRoots”的对象作为起始点,从这个节点向下搜索,搜 ...
- JVM垃圾回收——GC
一.JVM内存分配与回收 下图为堆内存结构图(注意:元数据区(MetaData )实际上不属于堆): 1.对象优先在Eden区分配 大多数情况下,对象在新生代中Eden区分配.当Eden区没有足够空间 ...
- Java基础--垃圾回收GC
GC: 垃圾回收由JVM中GC线程监控和执行. 参考: http://www.oracle.com/technetwork/java/gc-tuning-5-138395.html GC算法: 1. ...
- Java虚拟机-------垃圾回收机机制
概述 jvm中的堆图 在了解 垃圾回收器 之前,首先得了解一下垃圾回收器的几个名词. 1. 吞吐量CPU 用于运行用户代码的时间与 CPU 总消耗时间的比值.比如说虚拟机总运行了 100 分钟,用户代 ...
- JVM垃圾回收(GC)流程
/* 首先介绍一下JVM中堆内存的组成: JVM堆内存主要由三部分组成: (1)新生代: 伊甸园区,存活区,伸缩区 (2)老年代: 老年区,伸缩区 (3)元空间(永久代): 元空间,伸缩区 注意:JD ...
- JVM垃圾回收GC
1.堆的分代和区域 (年轻代)Young Generation(eden.s0.s1 space) Minor GC (老年代)Old Generation (Tenured space) ...
随机推荐
- Jenkins控制台乱码修改
原文地址:https://www.jianshu.com/p/8b9df45df401 方案一. 设置jenkins所在服务器环境变量,右键我的电脑→属性→高级系统设置→环境变量,添加JAVA_TOO ...
- miniconda3 安装tensorflow
使用miniconda3进行安装 conda create -n tensorflow conda install tensorflow 输入下面的代码进行测试 import tensorflow a ...
- 通用mybatis单表操作接口
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "- ...
- 《Mysql - Mysql 是如何保证主备一致的?》
一:Mysql 主备的基本原理? - 主备切换流程(M-S 架构) - - 在状态 1 中,客户端的读写都直接访问节点 A,而节点 B 是 A 的备库,只是将 A 的更新都同步过来,到本地执行. - ...
- (2)Spring Boot配置
文章目录 配置文件 YAML 语法 单元测试 配置文件值自动注入 @Value 获取配置文件属性的值 加载指定配置文件 优先级问题 加载Spring 的配置文件 为容器中添加组件 随机数 & ...
- k8s 证书反解
k8s证书反解 1.将k8s配置文件(kubelet.kubeconfig)中client-certificate-data:内容拷贝 2.echo "client-certificate- ...
- dotnet Core学习之旅(序)
.NET Core 新玩具,新工具,新生产力 我将在博客园我从0.1开始探索.NET Core 的过程. 为什么是从0.1开始而不是从0开始 我在微软刚宣布开源的时候便接触到了.NET Core 1. ...
- 杭电1081 第二道 dfs题
Problem Description 呃......变形课上Harry碰到了一点小麻烦,因为他并不像Hermione那样能够记住所有的咒语而随意的将一个棒球变成刺猬什么的,但是他发现了变形咒语的一个 ...
- Go part 6 接口,接口排序,接口嵌套组合,接口与类型转换,接口断言
接口 接口是一种协议,比如一个汽车的协议,就应该有 “行驶”,“按喇叭”,“开远光” 等功能(方法),这就是实现汽车的协议规范,完成了汽车的协议规范,就实现了汽车的接口,然后使用接口 接口的定义:本身 ...
- python之简单爬取一个网站信息
requests库是一个简介且简单的处理HTTP请求的第三方库 get()是获取网页最常用的方式,其基本使用方式如下 使用requests库获取HTML页面并将其转换成字符串后,需要进一步解析HTML ...