JVM GC机制
垃圾收集主要是针对堆和方法区进行。
回收机制:
现在的JVM基本都使用分代回收机制,把堆中内存区域分为新生代,老年代。
新生代:
| Eden(80%) | Survivor0(10%) | Survivor1(10%) |
老年代:
| Old place |
回收算法:
Minor GC:发生在新生代,内存空间小,频繁执行,所以一般执行速度很快。
Full GC(Major GC):Major GC发生在老年代,一般会伴随着一次Minor GC,所以也叫Full GC,一般执行速度较慢。
在新生代中采用复制算法,每个新对象都最先在Eden里,当Eden满了之后(此时两个Survivor都为空),将触发一次Minor GC,Eden里存活的对象就会送到Survivor0中,即 Eden→Survivor0,Eden里对象清空。
下一次Eden区满之后,就将Eden和Survivor0中存活的对象放到Survivor1中,即Eden+Survivor0→Survivor1。下次Eden满了之后,Eden+Survivor1→Survivor0..........................
如此循环,当对象的复制次数达到16次时,对象就会被送到老年代。
当新生代中对象放入老年代,而老年代中空间不足时,将会进行Full GC。
为什么需要Survivor,又为什么需要两个呢?
先假设没有Survivor:
Eden中的对象经历Minor GC后送到Old place,因为Minor GC很频繁,那么Old place很快就被填满了,然后进行Full GC,然而Full GC很消耗时间,会影响程序的执行速度和响应速度。
若增大Old place的空间,虽然Full GC的频率降低了,但是每次Full GC的时间增长了。若减小Old place的空间,Full GC的时间减少,但是频率增加了。
由此可见,增加Survivor的作用是,减少送往老年代的对象,从而降低Full GC的频率。
再假设只有一个Survivor:
Eden中的对象经历Minor GC后送到空的Survivor,此时没有什么问题,再然后又经历Minor GC,此时Survivor中有些对象死亡,而新的对象从Eden中过来,就出现了碎片化的问题。

由此可见,加一个Survivor是不可取的,至少的加两个,那为什么不三个四个呢?我觉得可能是因为新生代和老年代的空间大小比例有关,若增加多了Survivor,则会降低老年代的利用率,所以选择了两个Survivor。
所以设置两个Survivor的原因就是,解决碎片化。
回收器:
新生代:
Serial回收器:
串行回收器,Client 模式下的默认新生代收集器,是一个单线程的回收器,所以对于只有一个CPU来说,利用率最高。
ParNew回收器:
并行回收器,Server 模式下的虚拟机首选新生代收集器,能与CMS回收器配合,是多线程版的Serial,默认开启线程数量与CPU核数相同,可以使用 -XX:ParallelGCThreads 参数来设置线程数。
Parallel Scavenge回收器:
同样是多线程,但是其余回收器都是以缩短“垃圾回收时间”为主,而Parallel Scavenge的目标是达到一个可控制的吞吐量,它被称为“吞吐量优先”收集器。这里的吞吐量指 CPU 用于运行用户代码的时间占总时间的比值。
停顿时间越短就越适合需要与用户交互的程序,良好的响应速度能提升用户体验。而高吞吐量则可以高效率地利用 CPU 时间,尽快完成程序的运算任务,适合在后台运算而不需要太多交互的任务。
老年代:
Serial Old回收器:
同Serial回收器。
Parallel Old回收器:
同Parallel Scavenge回收器。
CMS回收器:
CMS是Concurrent(同时发生的)- Mark(标记)- Sweep(清理),所以此回收器采用标记-清理算法。分为以下四个步骤:
1、初始标记:仅仅只是标记一下 GC Roots 能直接关联到的对象,速度很快,需要停顿。
2、并发标记:进行 GC Roots Tracing 的过程,它在整个回收过程中耗时最长,不需要停顿。
3、重新标记:为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,需要停顿。
4、并发清除:不需要停顿。
在整个过程中耗时最长的并发标记和并发清除过程中,收集器线程都可以与用户线程一起工作,不需要进行停顿。
G1回收器:
G1(Garbage-First),它是一款面向服务端应用的垃圾收集器,在多 CPU 和大内存的场景下有很好的性能。HotSpot 开发团队赋予它的使命是未来可以替换掉 CMS 收集器。
堆被分为新生代和老年代,其它收集器进行收集的范围都是整个新生代或者老年代,而 G1 可以直接对新生代和老年代一起回收。
参考资料:
JVM GC机制的更多相关文章
- JVM GC 机制与性能优化
目录(?)[+] 1 背景介绍 与C/C++相比,JAVA并不要求我们去人为编写代码进行内存回收和垃圾清理.JAVA提供了垃圾回收器(garbage collector)来自动检测对象的作用域),可自 ...
- 理解JVM GC
理解JVM GC对于我们把控Java应用有很大的帮助.下面我从运维角度,把网上的JVM相关的资料整理如下,以加深对JVM GC的理解.如有错误的地方,请看官指正. JVM内存使用分类 JVM的内存分区 ...
- 直击面试,聊聊 GC 机制
前言 文章来源:https://studyidea.cn/ GC 中文直译垃圾回收,是一种回收内存空间避免内存泄漏的机制.当 JVM 内存紧张,通过执行 GC 有效回收内存,转而分配给新对象从而实现内 ...
- 聊聊面试中常问的GC机制
GC 中文直译垃圾回收,是一种回收内存空间避免内存泄漏的机制.当 JVM 内存紧张,通过执行 GC 有效回收内存,转而分配给新对象从而实现内存的再利用. JVM GC 机制虽然无需开发主动参与,减轻不 ...
- 【转载】Java性能优化之JVM GC(垃圾回收机制)
文章来源:https://zhuanlan.zhihu.com/p/25539690 Java的性能优化,整理出一篇文章,供以后温故知新. JVM GC(垃圾回收机制) 在学习Java GC 之前,我 ...
- JVM的 GC机制和内存管理
GC机制:java垃圾回收机制,垃圾收集器线程(Garbage Collection Thread)在 JVM 处于空闲循环式,会自动回收无用的内存块. 垃圾收集算法:1.引用计数 2.根搜索 3 ...
- JVM内存管理及GC机制
一.概述 Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代码,对内存泄露 ...
- 深入JVM系列(二)之GC机制、收集器与GC调优
一.回想JVM内存分配 须要了解很多其它内存模式与内存分配的,请看 深入JVM系列(一)之内存模型与内存分配 1.1.内存分配: 1.对象优先在EDEN分配 2.大对象直接进入老年代 3.长期存活的 ...
- Java性能优化之JVM GC(垃圾回收机制)
Java的性能优化,整理出一篇文章,供以后温故知新. JVM GC(垃圾回收机制) 在学习Java GC 之前,我们需要记住一个单词:stop-the-world .它会在任何一种GC算法中发生.st ...
随机推荐
- paramiko__摘抄
# -*- coding:utf-8 -*-# Author: Dennis Huang__Author__ = "Dennis" import paramiko # ssh = ...
- vue axios上传文件实例
<head> <title></title> <meta charset="UTF-8"> <meta name=" ...
- jar包自动化部署---jenkins
B.Application Server SVN账号:svn://192.168.1.49/svn/keenyoda-trunk/xxxxxcht=xxxxx 安装jenkins:安装目录:/usr/ ...
- L358 World Book Day
World Book Day is celebrated by UNESCO and other related organisations every year on the 23rd of Apr ...
- Python第三章(北理国家精品课 嵩天等)
一.数字类型及其操作 整数:pow(x,y),想算多大,就算多大:以0b或0B开头表示二进制:以0o或0O开头表示八进制:以0x或0X开头表示十六进制. 浮点数:取值范围-10^308至10^308, ...
- IP通信基础课堂笔记----关于数链层
课前回顾 IOS从上到下分别有:应用层,传输层,网络层,数链层,物理层. IP是网络层的地址,MAC是数链层的地址,IP必须通过ARP才能转换成MAC地址. 课堂内容 1.如何在数链层实现发送端数据无 ...
- Labview笔记-创建自定义控件
labview中的控件种类很多,但是样式或者外观有时不能满足我们的需求.如何制作一个好看酷酷的自定义控件呢? 以开关为例,我们先添加一个labview中自带的确定开关控件 之后右键该控件--高级--自 ...
- UML作业第三次:分析《书店图书销售管理系统》,绘制类图
一. 类图语法学习小结(类间关系的表示方法) 1.抽象类和接口 我们用关键字abstract或abstract class来定义抽象类(抽象类用斜体显示).也可以使用interface,annotat ...
- Oracle中计算两个日期时间的差
--方法1 select floor((sysdate - to_date('2006-09-01 08:00:00', 'yyyy-mm-dd hh24:mi:ss'))) as sDays fro ...
- python基础—sys与os库
python可以用sys库打印环境变量或者查看当前文件的脚本路径,具体代码: import sysprint(sys.path[2])#打印环境变量print(sys.argv)#当前脚本路径 os库 ...