7种jvm垃圾回收器,这次全部搞懂
前言
之前我们讲解了jvm
的组成结构
与垃圾回收算法
等知识点,今天我们来讲讲jvm最重要的堆内存
是如何使用垃圾回收器
进行垃圾回收,并且如何使用命令
去配置使用这些垃圾回收器。
堆内存详解
上面这个图大家应该已经很明白了吧。大家就可以理解成一个房子
被分成了几个房间
,每个房间的作用不同而已,有的是婴儿住的,有的是父母住的,有的是爷爷奶奶住的
堆内存被划分为
两块
,一块的年轻代
,另一块是老年代
。年轻代又分为
Eden
和survivor
。他俩空间大小比例默认为8:2,幸存区又分为
s0
和s1
。这两个空间大小是一模一样的,就是一对双胞胎,他俩是1:1的比例
堆内存垃圾回收过程
第一步
新生成
的对象首先放到Eden
区,当Eden区满了
会触发Minor GC
。
第二步
第一步GC活下来的对象,会被移动到survivor
区中的S0区,S0区满了之后会触发Minor GC
,S0区存活下来的对象会被移动到S1区,S0区空闲。
S1满了之后在GC,存活下来的再次移动到S0区,S1区空闲,这样反反复复GC,每GC一次,对象的年龄就涨一岁
,达到某个值后(15),就会进入老年代
。
第三步
在发生一次Minor GC
后(前提条件),老年代可能会出现Major GC
,这个视垃圾回收器而定。
Full GC触发条件
手动调用System.gc,会不断的执行Full GC
老年代空间不足/满了
方法区空间不足/满了
注意
们需要记住一个单词:stop-the-world
。它会在任何一种GC算法中发生。stop-the-world 意味着JVM因为需要执行GC而停止
应用程序的执行。
当stop-the-world 发生时,除GC所需的线程外,所有的线程
都进入等待
状态,直到GC任务完成。GC优化很多时候就是减少stop-the-world 的发生。
回收哪些区域的对象
需要注意的是,JVM GC只回收堆内存
和方法区内
的对象。而栈内存
的数据,在超出作用域后会被JVM自动释放掉,所以其不在JVM GC的管理范围内。
堆内存常见参数配置
参数 | 描述 |
---|---|
-Xms | 堆内存初始大小,单位m、g |
-Xmx | 堆内存最大允许大小,一般不要大于物理内存的80% |
-XX:PermSize | 非堆内存初始大小,一般应用设置初始化200m,最大1024m就够了 |
-XX:MaxPermSize | 非堆内存最大允许大小 |
-XX:NewSize(-Xns) | 年轻代内存初始大小 |
-XX:MaxNewSize(-Xmn) | 年轻代内存最大允许大小 |
-XX:SurvivorRatio=8 | 年轻代中Eden区与Survivor区的容量比例值,默认为8,即8:1 |
-Xss | 堆栈内存大小 |
-XX:NewRatio=老年代/新生代 | 设置老年代和新生代的大小比例 |
-XX:+PrintGC | jvm启动后,只要遇到GC就会打印日志 |
-XX:+PrintGCDetails | 查看GC详细信息,包括各个区的情况 |
-XX:MaxDirectMemorySize | 在NIO中可以直接访问直接内存,这个就是设置它的大小,不设置默认就是最大堆空间的值-Xmx |
-XX:+DisableExplicitGC | 关闭System.gc() |
-XX:MaxTenuringThreshold | 垃圾可以进入老年代的年龄 |
-Xnoclassgc | 禁用垃圾回收 |
-XX:TLABWasteTargetPercent | TLAB占eden区的百分比,默认是1% |
-XX:+CollectGen0First | FullGC时是否先YGC,默认false |
TLAB 内存
TLAB全称是Thread Local Allocation Buffer即线程本地分配缓存
,从名字上看是一个线程专用的内存分配区域,是为了加速对象分配而生的。
每一个线程都会产生一个TLAB,该线程独享的工作区域,java虚拟机使用这种TLAB区来避免多线程冲突问题,提高了对象分配的效率。
TLAB空间一般不会太大,当大对象无法在TLAB分配时,则会直接分配到堆上。
参数 | 描述 |
---|---|
-Xx:+UseTLAB | 使用TLAB |
-XX:+TLABSize | 设置TLAB大小 |
-XX:TLABRefillWasteFraction | 设置维护进入TLAB空间的单个对象大小,他是一个比例值,默认为64,即如果对象大于整个空间的1/64,则在堆创建 |
-XX:+PrintTLAB | 查看TLAB信息 |
-Xx:ResizeTLAB | 自调整TLABRefillWasteFraction阀值。 |
垃圾回收器总览
新生代可配置的回收器:Serial、ParNew、Parallel Scavenge
老年代配置的回收器:CMS、Serial Old、Parallel Old
新生代和老年代区域的回收器之间进行连线,说明他们之间可以搭配使用。
新生代垃圾回收器
Serial 垃圾回收器
Serial收集器是最基本的、发展历史最悠久的收集器。俗称为:串行回收器
,采用复制算法
进行垃圾回收
特点
串行回收器是指使用单线程进行垃圾回收的回收器。每次回收时,串行回收器只有一个工作线程。
对于并行能力较弱的单CPU计算机来说,串行回收器的专注性和独占性往往有更好的性能表现。
它存在Stop The World问题,及垃圾回收时,要停止程序的运行。
使用-XX:+UseSerialGC
参数可以设置新生代使用这个串行回收器
ParNew 垃圾回收器
ParNew其实就是Serial的多线程
版本,除了使用多线程之外,其余参数和Serial一模一样。俗称:并行垃圾回收器
,采用复制算法
进行垃圾回收
特点
ParNew默认开启的线程数与CPU数量相同,在CPU核数很多的机器上,可以通过参数-XX:ParallelGCThreads
来设置线程数。
它是目前新生代首选的垃圾回收器,因为除了ParNew之外,它是唯一一个能与老年代CMS配合工作的。
它同样存在Stop The World问题
使用-XX:+UseParNewGC
参数可以设置新生代使用这个并行回收器
ParallelGC 回收器
ParallelGC使用复制算法回收垃圾,也是多线程的。
特点
就是非常关注系统的吞吐量,吞吐量
=代码运行时间
/(代码运行时间
+垃圾收集时间
)
-XX:MaxGCPauseMillis
:设置最大垃圾收集停顿时间,可用把虚拟机在GC停顿的时间控制在MaxGCPauseMillis范围内,如果希望减少GC停顿时间可以将MaxGCPauseMillis设置的很小,但是会导致GC频繁
,从而增加了GC的总时间
,降低
了吞吐量
。所以需要根据实际情况设置该值。
-Xx:GCTimeRatio
:设置吞吐量大小,它是一个0到100之间的整数,默认情况下他的取值是99
,那么系统将花费不超过1/(1+n)
的时间用于垃圾回收,也就是1/(1+99)=1%
的时间。
另外还可以指定-XX:+UseAdaptiveSizePolicy
打开自适应模式,在这种模式下,新生代的大小、eden、from/to的比例,以及晋升老年代的对象年龄参数会被自动调整,以达到在堆大小、吞吐量和停顿时间之间的平衡点。
使用-XX:+UseParallelGC参数可以设置新生代使用这个并行回收器
老年代垃圾回收器
SerialOld 垃圾回收器
SerialOld是Serial回收器的老年代
回收器版本,它同样是一个单线程
回收器。
用途
一个是在JDK1.5及之前的版本中与Parallel Scavenge收集器搭配使用,
另一个就是作为CMS收集器的后备预案,如果CMS出现Concurrent Mode Failure,则SerialOld将作为后备收集器。
使用算法
:标记 - 整理算法
ParallelOldGC 回收器
老年代ParallelOldGC
回收器也是一种多线程的回收器,和新生代的ParallelGC回收器一样,也是一种关注吞吐量的回收器,他使用了标记压缩算法
进行实现。
-XX:+UseParallelOldGc
进行设置老年代使用该回收器
-XX:+ParallelGCThreads
也可以设置垃圾收集时的线程数量。
CMS 回收器
CMS全称为:Concurrent Mark Sweep意为并发标记清除,他使用的是标记清除法
。主要关注系统停顿时间。
使用-XX:+UseConcMarkSweepGC
进行设置老年代使用该回收器。
使用-XX:ConcGCThreads
设置并发线程数量。
特点
CMS并不是独占的回收器,也就说CMS回收的过程中,应用程序仍然在不停的工作,又会有新的垃圾不断的产生,所以在使用CMS的过程中应该确保应用程序的内存足够可用。
CMS不会等到应用程序饱和
的时候才去回收垃圾,而是在某一阀值的时候开始回收,回收阀值可用指定的参数进行配置:-XX:CMSInitiatingoccupancyFraction
来指定,默认为68
,也就是说当老年代的空间使用率
达到68%
的时候,会执行
CMS回收。
如果内存使用率增长的很快,在CMS执行的过程中,已经出现了内存不足的情况,此时CMS回收就会失败,虚拟机将启动老年代串行
回收器;SerialOldGC
进行垃圾回收,这会导致应用程序中断,直到垃圾回收完成后才会正常工作。
这个过程GC的停顿时间可能较长,所以-XX:CMSInitiatingoccupancyFraction
的设置要根据实际的情况。
之前我们在学习算法的时候说过,标记清除法有个缺点就是存在内存碎片
的问题,那么CMS有个参数设置-XX:+UseCMSCompactAtFullCollecion
可以使CMS回收完成之后进行一次碎片整理
。
-XX:CMSFullGCsBeforeCompaction
参数可以设置进行多少次CMS回收之后,对内存进行一次压缩
。
G1 回收器
篇幅太长,我们下篇文章讲解!!!
7种jvm垃圾回收器,这次全部搞懂的更多相关文章
- 【转】Java学习---垃圾回收算法与 JVM 垃圾回收器综述
[原文]https://www.toutiao.com/i6593931841462338062/ 垃圾回收算法与 JVM 垃圾回收器综述 我们常说的垃圾回收算法可以分为两部分:对象的查找算法与真正的 ...
- 垃圾回收算法与 JVM 垃圾回收器综述(转)
垃圾回收算法与 JVM 垃圾回收器综述 我们常说的垃圾回收算法可以分为两部分:对象的查找算法与真正的回收方法.不同回收器的实现细节各有不同,但总的来说基本所有的回收器都会关注如下两个方面:找出所有的存 ...
- JVM 垃圾回收器工作原理及使用实例介绍(转载自IBM),直接复制粘贴,需要原文戳链接
原文 https://www.ibm.com/developerworks/cn/java/j-lo-JVMGarbageCollection/ 再插一个关于线程和进程上下文,待判断 http://b ...
- Jvm垃圾回收器(终结篇)
知识回顾: 第一篇<Jvm垃圾回收器(基础篇)>主要讲述了判断对象的生死?两种基础判断对象生死的算法.引用计数法.可达性分析算法,方法区的回收.在第二篇<Jvm垃圾回收器(算法篇)& ...
- JVM基础系列第9讲:JVM垃圾回收器
前面文章中,我们介绍了 Java 虚拟机的内存结构,Java 虚拟机的垃圾回收机制,那么这篇文章我们说说具体执行垃圾回收的垃圾回收器. 总的来说,Java 虚拟机的垃圾回收器可以分为四大类别:串行回收 ...
- Jvm垃圾回收器(算法篇)
在<Jvm垃圾回收器(基础篇)>中我们主要学习了判断对象是否存活还是死亡?两种基础的垃圾回收算法:引用计数法.可达性分析算法.以及Java引用的4种分类:强引用.软引用.弱引用.虚引用.和 ...
- JVM垃圾回收器原理及使用介绍
JVM垃圾回收器原理及使用介绍 垃圾收集基础 引用计数法(Reference Counting) 标记-清除算法(Mark-Sweep) 复制算法(Copying) 标记-压缩算法(Mark-Comp ...
- Hotspot JVM垃圾回收器
前两篇<JVM入门——运行时数据区><JVM常见垃圾回收算法>所提到的实际上JVM规范以及常用的垃圾回收算法,具体的JVM实现实际上不止一种,有JRockit.J9等待,当然最 ...
- jvm垃圾回收器介绍
上篇文章中我们讨论了jvm的内存区域,这篇文章我们来讨论针对的内存区域的垃圾回收机制. 其实针对垃圾回收我们通常考虑三个问题:1.哪些内存需要回收?2.什么时候回收?3.如何回收?下面我们针对这三个问 ...
随机推荐
- 第4篇 Scrum 冲刺博客(专✌️团队)
一.站立式会议 1.1会议图片 1.2成员完成情况 成员 昨天完成的任务 今天计划完成的任务 工作中的困难 陈忠明 按下载热度返回歌曲信息,与前端尝试交互 歌曲信息的上传/下载包 前后端交互问题 吴茂 ...
- Java面试题(JVM篇)
JVM 194.说一下 jvm 的主要组成部分?及其作用? 类加载器(ClassLoader) 运行时数据区(Runtime Data Area) 执行引擎(Execution Engine) 本地库 ...
- 开启gzip压缩/cdn是否会影响抓取和收录量
http://www.wocaoseo.com/thread-291-1-1.html 服务器开启gzip压缩是否会影响蜘蛛抓取和收录量?站点开了CDN,对百度SEO影响有多大?我发现我们站自从开了C ...
- layui 表单验证汇总
1 表单自带校验 lay-verify:是表单验证的关键字有以下值供选择: required 必填项phone 手机号email 邮箱date 日期url 链接identity 身份证number 数 ...
- HDU-多校2-Everything Is Generated In Equal Probability(公式+逆元)
Problem Description One day, Y_UME got an integer N and an interesting program which is shown below: ...
- 12_Python语法示例(函数)
1.写一个函数mysum,此函数带有两个参数x,y打印出两个参数x,y的和 def mysum(x, y): print(x + y) mysum(3, 2) 2.写一个函数print_even,传入 ...
- WebApi 接口传参接参
阅读目录 一.get请求 1.基础类型参数 2.实体作为参数 3.数组作为参数 4.“怪异”的get请求 二.post请求 1.基础类型参数 2.实体作为参数 3.数组作为参数 4.后台发送请求参数的 ...
- ZT:通过Find命令找到你要找的东西
https://os.51cto.com/art/202003/612049.htm find 命令有巨多的选项可以帮助你准确定位你在 Linux 系统上需要寻找的文件.这篇文章讨论了一系列非常有用的 ...
- 哪些方法可以绕过PowerShell Execution Policy?
哪些方法可以绕过PowerShell Execution Policy? 转: https://blog.csdn.net/qq_27446553/article/details/50577296
- HTML5总结整理
(仅供大家学习分享交流) 一.简介 1.前端开发最核心技术 我们知道,用所谓的网页三剑客已经不能满足需求了,那前端开发究竟要学习什么技术呢?网页最 主要由3部分组成:结构.表现和行为.网页现在新的标准 ...