jvm系列二之GC收集器

目录

  • 参考
  • 概念理解
    • 并发和并行
    • 吞吐量
  • GC垃圾收集器
    • Serial New收集器
    • Parallel New(并行)收集器
    • Parallel Scavenge(并行)收集器
    • Serial Old(串行)收集器
    • Parallel Old(并行)收集器
    • CMS收集器
    • G1收集器(JDK)

参考

发现有个作者整理的已经很详细了,笔者仅做一些简单的修改记录在这里,方便查阅自己的理解。原文《java垃圾收集器》基本是对《深入理解java虚拟机》一书的总结。另外笔者还参考了Java Garbage Collection Basics。

概念理解

并发和并行

这两个名词都是并发编程中的概念,在谈论垃圾收集器的上下文语境中,它们可以解释如下。
并行(Parallel):指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态。

并发(Concurrent):指用户线程与垃圾收集线程同时执行(但不一定是并行的,可能会交替执行),用户程序在继续运行,而垃圾收集程序运行于另一个CPU上。

虽然原书是这么讲的,总感觉不对,所以查阅了文档,私以为只是作者没有描述清楚

吞吐量

吞吐量就是CPU用于运行用户代码的时间与CPU总消耗时间的比值,即吞吐量 = 运行用户代码时间 /(运行用户代码时间 + 垃圾收集时间)。
虚拟机总共运行了100分钟,其中垃圾收集花掉1分钟,那吞吐量就是99%。

GC垃圾收集器

这里写图片描述

图中展示了7种作用于不同分代的收集器,如果两个收集器之间存在连线,就说明它们可以搭配使用。虚拟机所处的区域,则表示它是属于新生代收集器还是老年代收集器。

Serial New收集器

特性

  • 最基本的收集器
  • 针对新生代的收集器,采用的是复制算法
  • 单线程
  • 能与CMS收集器配合工作

优势
简单而高效(与其他收集器的单线程比),对于限定单个CPU的环境来说,Serial收集器由于没有线程交互的开销,专心做垃圾收集自然可以获得最高的单线程收集效率。

应用场景
Serial收集器是虚拟机运行在Client模式下的默认新生代收集器。

Parallel New(并行)收集器

特性

  • 使用多线程进行垃圾收集(Serial的多线程版本)
  • 新生代采用复制算法,老年代采用标记整理
  • 能与CMS收集器配合工作
  • -XX:UseConcMarkSweepGC的默认新生代收集器
  • 可以通过-XX:UseParNewGC选项强制指定
  • -XX:ParallelGCThreads参数可以限制垃圾收集线程数

应用场景
ParNew收集器是许多运行在Server模式下的虚拟机中首选的新生代收集器。
主要原因是:除了Serial收集器外,目前只有它能与CMS收集器配合工作。

Parallel Scavenge(并行)收集器

  • 与ParNew类似的是,都是用于年轻代回收的使用复制算法的并行收集器
  • 该收集器的目标是达到一个可控制的吞吐量,其中吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)
  • Parallel Scavenge提供了两个参数用以精确控制吞吐量,分别是用以控制最大GC停顿时间的-XX:MaxGCPauseMillis及直接控制吞吐量的参数-XX:GCTimeRatio.
  • MaxGCPauseMiilis:单位为ms,适用于高用户体验的场景,虚拟机将尽力保证每次MinorGC耗时不超过所设时长,但并不是该时间越小越好,因为GC耗时缩短是用调小年轻代获取的,回收500m的对象肯定要比回收2000m的对象耗时更短,但是回收频率也大大增大了,吞吐量也随之下去了。使用该参数的理论效果:MaxGCPauseMillis越小,单次MinorGC的时间越短,MinorGC次数增多,吞吐量降低。
  • GCTimeRatio:从字面意思上理解是花费在GC上的时间占比,但是实际含义并非如此,GC耗时的计算公式为1/(1+n),n为GCTimeRatio,因此,GCTimeRatio的实际用途是直接指定吞吐量。GCTimeRatio的默认值为99,因此,GC耗时的占比应为1/(1+99)=1%。使用参数的理论效果:GCTimeRatio越大,吞吐量越大,GC的总耗时越小。有可能导致单次MinorGC耗时变长。适用于高运算场景。
  • 此外,还有个参数和以上两个参数息息相关,那就是-XX:+UseAdaptiveSizePolicy,默认为启用,搭配MaxGCPauseMillis或GCTimeRatio使用,打开该开关后,虚拟机将根据当前系统运行情况收集性能监控信息,动态调整SurvivorRatio,PretenureSizeThreshold等细节参数。

使用场景
该收集器是server模式下的默认收集器,也可-XX:+UseParallelGC强制使用该收集器,打开该收集器后,将使用Parallel Scavenge(年轻代)+Serial Old(老年代)的组合进行GC。

Serial Old(串行)收集器

特性
Serial New收集器的老年代版本,使用用标记整理算法

使用场景

主要意义是提供给client模式下的虚拟机用。
虚拟机在Server模式下有两大用途:

  1. JDK<=1.5的虚拟机中与Parallel Scavenge(并行)收集器搭配使用
  2. 作为CMS收集器的后备方案

Parallel Old(并行)收集器

特性

  • Parallel Scavenge收集器的老年代版本
  • 针对老年代,多线程,标记整理算法

使用场景
在注重吞吐量以及CPU资源敏感的场合,都可以优先考虑Parallel Scavenge加Parallel Old收集器。

这个收集器是在JDK 1.6中才开始提供的,在此之前,新生代的Parallel Scavenge收集器一直处于比较尴尬的状态。原因是,如果新生代选择了Parallel Scavenge收集器,老年代除了Serial Old收集器外别无选择(Parallel Scavenge收集器无法与CMS收集器配合工作)。由于老年代Serial Old收集器在服务端应用性能上的“拖累”,使用了Parallel Scavenge收集器也未必能在整体应用上获得吞吐量最大化的效果,由于单线程的老年代收集中无法充分利用服务器多CPU的处理能力,在老年代很大而且硬件比较高级的环境中,这种组合的吞吐量甚至还不一定有ParNew加CMS的组合“给力”。直到Parallel Old收集器出现后,“吞吐量优先”收集器终于有了比较名副其实的应用组合。

CMS收集器

特性
CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。目前很大一部分的Java应用集中在互联网站或者B/S系统的服务端上,这类应用尤其重视服务的响应速度,希望系统停顿时间最短,以给用户带来较好的体验。CMS收集器就非常符合这类应用的需求。

运作过程

CMS收集器是基于“标记—清除”算法实现的,它的运作过程相对于前面几种收集器来说更复杂一些,整个过程分为4个步骤:

初始标记(CMS initial mark)

初始标记仅仅只是标记一下GC Roots能直接关联到的对象,速度很快,需要“Stop The World”。

并发标记(CMS concurrent mark)

并发标记阶段就是进行GC Roots Tracing的过程。

重新标记(CMS remark)

重新标记阶段是为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短,仍然需要“Stop The World”。

并发清除(CMS concurrent sweep)

并发清除阶段会清除对象。

由于整个过程中耗时最长的并发标记和并发清除过程收集器线程都可以与用户线程一起工作,所以,从总体上来说,CMS收集器的内存回收过程是与用户线程一起并发执行的。

优点
CMS是一款优秀的收集器,它的主要优点在名字上已经体现出来了:并发收集、低停顿。

缺点

1.CMS收集器对CPU资源非常敏感
其实,面向并发设计的程序都对CPU资源比较敏感。在并发阶段,它虽然不会导致用户线程停顿,但是会因为占用了一部分线程(或者说CPU资源)而导致应用程序变慢,总吞吐量会降低。

  1. CMS默认启动的回收线程数是(CPU数量+3)/ 4,也就是当CPU在4个以上时,并发回收时垃圾收集线程不少于25%的CPU资源,并且随着CPU数量的增加而下降。但是当CPU不足4个(譬如2个)时,CMS对用户程序的影响就可能变得很大。
  2. CMS收集器无法处理浮动垃圾
    CMS收集器无法处理浮动垃圾,可能出现“Concurrent Mode Failure”失败而导致另一次Full GC的产生。由于CMS并发清理阶段用户线程还在运行着,伴随程序运行自然就还会有新的垃圾不断产生,这一部分垃圾出现在标记过程之后,CMS无法在当次收集中处理掉它们,只好留待下一次GC时再清理掉。这一部分垃圾就称为“浮动垃圾”。也是由于在垃圾收集阶段用户线程还需要运行,那也就还需要预留有足够的内存空间给用户线程使用,因此CMS收集器不能像其他收集器那样等到老年代几乎完全被填满了再进行收集,需要预留一部分空间提供并发收集时的程序运作使用。要是CMS运行期间预留的内存无法满足程序需要,就会出现一次“Concurrent Mode Failure”失败,这时虚拟机将启动后备预案:临时启用Serial Old收集器来重新进行老年代的垃圾收集,这样停顿时间就很长了。
  3. CMS收集器会产生大量空间碎片
    CMS是一款基于“标记—清除”算法实现的收集器,这意味着收集结束时会有大量空间碎片产生。空间碎片过多时,将会给大对象分配带来很大麻烦,往往会出现老年代还有很大空间剩余,但是无法找到足够大的连续空间来分配当前对象,不得不提前触发一次Full GC。

G1收集器(JDK)

Getting Started with the G1 Garbage Collector

堆内存分配

G1的堆内存被分成许多固定大小的区域。区域大小相同,在JVM启动时确定。JVM通常管理2000个区域,区域大小介于1M到32M之间。
这些区域被映射为逻辑上的Eden、survivor和老年代区域,相同类型区域地址可以不连续。
堆内存分配

区域分为五种,Eden、survivor和老年代,另外还有一种大对象区(Humongous),Humongous区域用来存放占据50%以上区域空间的对象,这些对象被存储在一组连续区域内,最后一种区域就是未被使用区域。

G1的Young GC

存活对象移动到一个或多个survivor区域。如果对象达到晋升年龄,将被移动到老年代区域。这一阶段会Stop The World(STW)。

G1老年代垃圾回收

G1回收器在对内存的老年代区域执行以下阶段。注意这些阶段也包括新生代的回收。

阶段描述
初始标记(STW)捎带一次youngGC。标记可能引用了老年代区域对象的survivor区域(根区域)
根区域扫描扫描根区域中指向老年代的引用。与应用线程并发。此阶段完成后才可以进行youngGC
并发标记全堆扫描存活对象。与应用线程并发。这一阶段可以被youngGC打断
重新标记STW完成堆中所有存活对象的扫描,使用snapshot-at-the-beginningSATB算法
清除统计存活对象和空区域(STW),更新RSets(STW),重置空区域,加入空白列表(并发)
复制STW将存活对象移动至未使用区域

转载于:https://www.cnblogs.com/mcai/p/9642377.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/352802.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

shell脚本中一些特殊符号

在shell中常用的特殊符号罗列如下&#xff1a; # ; ;; . , / \\ string| ! $ ${} $? $$ $* \"string\"* ** ? : ^ $# $ command{} [] [[]] () (()) || && {xx,yy,zz,...}~ ~ ~- & \\<...\\> - % ! # 井号 (…

java 并发执行_Java并发执行器的懒惰开发人员简介

java 并发执行如果我告诉您util.concurrent API自2004年起提供此类服务&#xff0c;我就会自欺欺人。但是&#xff0c;我想回顾一下一些很酷的功能。 并发专家&#xff0c;现在是时候关闭该窗口了。 所有其他人&#xff0c;请保持紧紧的乐趣。 你不会忘记你的根源 执行程序是具…

球球大作战测试服android版,球球大作战10.0体验服

在球球大作战10.0体验服中&#xff0c;2019球球们将迎来全新的冒险&#xff0c;多重外观&#xff0c;更加的绚丽夺目&#xff0c;探索新的地图&#xff0c;与不同的对手较量一番&#xff0c;无限吞噬&#xff0c;热血竞技&#xff0c;灵活的走位&#xff0c;搭配强力道具&#…

单线程的并发,协程

IO多路复用 作用:检测多个socket是否已经发生变化(是否已经连接成功/是否已经获取数据) setblocking(Flase) 让原本阻塞的变成非阻塞(不等待)状态 import socket import selectsk socket.socket() sk.setblocking(False) try:sk.connect(("www.baidu.com",80)) exce…

linux shell 字符串操作详解 (长度,读取,替换,截取,连接,对比,删除,位置 )

在做shell批处理程序时候&#xff0c;经常会涉及到字符串相关操作。有很多命令语句&#xff0c;如&#xff1a;awk,sed都可以做字符串各种操作。 其实shell内置一系列操作符号&#xff0c;可以达到类似效果&#xff0c;大家知道&#xff0c;使用内部操作符会省略启动外部程序等…

android.mk 模块编译,通过Android.mk添加一个编译模块到系统中的顺序如下

①LOCAL_PATH②CLEAR_VARS③LOCAL_SRC_FILES④LOCAL_CFLAGS(可选)⑤LOCAL_MODULE⑥LOCAL_STATIC_LIBRARIES(可选)⑦BUILD_XXX(12)Android.mk常用的变量变量名 说明LOCAL_PATH 用于确定源码所在的目录&#xff0c;最好把它放在CLEAR_VARS变量引用的前面&#xff0c;因为它不会被…

使用Spring Reactor Core进行分散收集

我在使用Netflix Rx-Java库方面有良好的工作经验&#xff0c;并且以前曾写过关于使用Rx-Java和Java 8 CompletableFuture解决分散式问题的博客。 在这里&#xff0c;我想探索使用Spring Reactor Core库应用相同的模式。 tldr –如果您熟悉Netflix Rx-Java&#xff0c;您已经很…

添加操作审计记录

1.所有操作审计记录 在环境变量/etc/profile中加入如下字段&#xff0c;可记录所有用户登录系统的操作 #history bash USERwhoami USER_IPwho -u am i 2>/dev/null| awk {print $NF}|sed -e s/[()]//g if [ "$USER_IP" "" ]; then USER_IPhostname fi …

android sharesdk分享功能,Android ShareSDK快速实现分享功能

第一步 &#xff1a;获取ShareSDK为了集成ShareSDK&#xff0c;您首先需要到ShareSDK官方网站注册并且创建应用&#xff0c;获得ShareSDK的Appkey&#xff0c;然后到SDK的下载页面下载SDK的压缩包&#xff0c;解压以后可以得到如下图的目录结构&#xff1a;ShareSDK在“ShareSD…

shell编程-分支语句

目标&#xff1a;完成这一章&#xff0c;你将能够作以下事情&#xff1a;描述条件分支语句中返回值的作用。 使用test命令来分析一个命令的返回值。 在shell程序中使用if和case结构。 1.返回值shell变量“&#xff1f;”中保存上一个被执行命令的返回值&#xff1a;0&#xff1…

android自定义表盘部件,Android自定义view仿支付宝芝麻信用表盘

演示效果实现步骤&#xff1a;1.画不同宽度和半径的内外圆弧2.通过循环旋转canvas&#xff0c;在固定位置绘制短线刻度&#xff0c;长线刻度&#xff0c;刻度文字3.绘制view中心几个文本&#xff0c;并调整位置4.实时更新当前旋转角度刷新小圆点位置&#xff1b;5.判断分数应该…

记录的详细操作

拷贝表拷贝结构 与数据create table copy_table select *from customer ;仅拷贝结构create table copy_table select *from customer where 0 > 1;共同点&#xff1a; 索引 描述&#xff08;自增&#xff09; 不能以下语法中记录的详细操作[] 表示可选的{}表示必选的增ins…

linux查看文件有多少行

使用wc命令 具体通过wc --help 可以查看。 如&#xff1a;wc -l filename 就是查看文件里有多少行 wc -w filename 看文件里有多少个word。 wc -L filename 文件里最长的那一行是多少个字。 wc命令 wc命令的功能为统计指定文件中的字节数、字数、行数, 并将统计结果显示输出。 …

java 消息通知_用Java弹出创建新的消息通知

java 消息通知首先创建JFrame作为弹出窗口。 在其中添加一些JLabel以包含信息&#xff0c;并在适当的位置分配它们&#xff0c;使其看起来像一条通知消息。 下面给出了示例代码&#xff1a; String message You got a new notification message. Isnt it awesome to have suc…

vs android 压缩,Android Studio是否压缩classes.dex文件?

看起来输出文件夹中apk文件的classes.dex与已安装的应用程序不同.我正在使用classes.dex文件来解决一些安全问题,所以通常我解压缩最终的apk文件并从classes.dex文件中获取信息.但是当我在运行时读取classes.dex文件时文件大小是如此不同. (8MB vs 46KB)应用程序本身工作得很好…

自己写的py文件中调用django models

import os os.environ[DJANGO_SETTINGS_MODULE] 项目名.settingsimport djangodjango.setup()from blog import modelsentry models.Entry.objects.get(pk1)tech_blog models.Blog.objects.get(name科技)print(entry, tech_blog) 转载于:https://www.cnblogs.com/dangrui072…

shell脚本 -d 是目录文件,那么-e,-f分别是什么?还有! -e这又是什么意思呢?

shell脚本 -d 是目录文件&#xff0c;那么-e&#xff0c;-f分别是什么?还有"&#xff01; -e"这又是什么意思呢&#xff1f; -e filename 如果 filename存在&#xff0c;则为真 -d filename 如果 filename为目录&#xff0c;则为真 -f filename 如果 filename为常规…

将Java应用程序作为Windows服务安装

这听起来像是您不需要的东西&#xff0c;但是有时候&#xff0c;当您分发最终用户软件时&#xff0c;可能需要将Java程序安装为Windows服务。 我之所以必须这样做&#xff0c;是因为我开发了一种用于公务员的工具 &#xff0c;可以自动将其Excel文件转换并将其推入我国的openda…

怎样实现banner自动播放html,纯CSS3实现banner图片自动轮播效果方式总结

自动轮播&#xff1a;实现切换图片&#xff0c;图片循环播放&#xff1b;鼠标悬停某张图片&#xff0c; 则暂停切换。css方法一、opacity控制透明度实现轮播效果依照需求咱们选择用CSS3的animation动画进行实现&#xff1b;transition动画须要触发才能启动&#xff0c;html因此…

你好a+b(非入门)

题目传送门&#xff1a;https://www.nowcoder.com/acm/contest/165/A来源&#xff1a;牛客网 牛牛刚学习了输入输出&#xff0c;他遇到了一道这样的题目。 输入2个整数a和b保证输入的a和b在long long范围之内&#xff0c;即满足-9223372036854775808 < a, b < 9223372036…