前言

垃圾收集算法是内存回收的方法论;垃圾收集器是内存回收的具体实现。Java虚拟机规范中对垃圾收集器应该如何实现并没有任何规定,因此不同的厂商、不同版本的虚拟机所提供的垃圾收集器都有很大的差别,并且一般都会提供参数供用户根据自己的应用特点和要求组合出各个年代所使用的收集器。
 
虚拟机里并不是使用一个收集器,而是很多收集器搭配使用,在不同的年代使用不同的收集器。

一、Serial收集器

Serial收集器是最基本、发展历史最悠久的收集器、曾经是虚拟机新生代收集的唯一选择。这个收集器是一个单线程的收集器,但它的“单线程”的意义并不仅仅说明它只会使用一个CPU或一条收集线程去完成垃圾收集工作,更重要的是在他进行垃圾收集时,必须暂停其他所有的工作线程,直到他收集结束。“Stop-The-World”这项工作实际是是由虚拟机在后台自动发起和自动完成的,在用户不可见的情况下把用户正常工作的线程全部停掉,这是比较难以接受的。
 

 

二、ParNew收集器

ParNew收集器就是Serial收集器的多线程版本,处理使用多条线程进行垃圾收集之外,其余行为包括Serail收集器可用的所有控制参数(例如:-XX:SurvivorRatio、-XX:PretenureSizeThreshold、-XX:HandlePromotionFailure等)、收集算法、Stop the World、对象分配规则、回收策略等都与Serail收集器完全一致,在实现上,两者也共用了很多代码。

ParNew收集器除了多线程收集之外,其他与Serial收集器相比并没有多大的创新之处,但它却是许多运行在Server模式下的虚拟机中首选的新生代收集器,其中有一个与性能无关但很重要的原因是,除了Serial收集器外,目前只有它能与CMS收集器配合工作。
 

三、Paraller Scanvenge收集器

Paraller Scanvenge收集器是一个新生代收集器,它也是使用复制算法的收集器,又是并行的多线程收集器。
 
Paraller Scanvenge收集器的特点是它的关注点与其他收集器不同,CMS等收集器的关注点是尽可能的缩短垃圾收集器收集时用户现程的停顿时间,而Paraller Scavenge收集器的目标这是达到一个可控制的吞吐量(Throughput)。所谓吞吐量就是CPU用于运行用户代码的时间与CPU总消耗时间的比值。即吞吐量=运行用户代码时间/(运行用户代码时间 + 垃圾收集时间)。
 
停顿时间越短越适合需要与用户交互的程序,良好的响应速度能提升用户体验,而高吞吐量则可以高效率的利用CPU时间,尽快的完成程序的运算任务,主要适合在后台运算而不需要太多交互的任务。
 
parallel Scavenge收集器提供了两个参数用于精确控制吞吐量,分别是控制最大垃圾收集器停顿时间的-XX:MaxGCPauseMillis参数以及直接设置吞吐量大小的-XX:GCTimeRatio参数。
 
MaxGCPauseMillis 参数允许的值是一个大于0的毫秒数,收集器将尽可能地保证内存回收花费的时间不超过设定值。
GCTimeRatio参数的值应当是一个大于0且小于100的整数,也就是垃圾收集时间占比总时间的比率。
 
注:

并行(Paraller):指多条来及收集线程并行工作,但此用户线程仍然处于等待状态
并发(Concurrent):值用户线程与垃圾收集线程同时执行(但不一定是并行的,可能会交替执行),用户程序在继续运行,而垃圾收集程序运行在另一个CPU上。
 

4、Serial Old收集器

Serial Old 收集器是Serial 收集器的老年代版本,它同样是一个单线程收集器,使用“标记-整理”算法。这个收集器的主要意义也是在与Client模式下的虚拟机使用。如果在Server模式下,那么他还有两大用途,一是在JDK1.5以及之前的版本中与Paraller Scavenge收集器搭配使用,另一种用途是做为CMS收集器的后备预案,在并发收集发生Concurrent Mode Failure时使用。
 

五、parallel Old 收集器

Paraller Old收集器是Paraller Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法。

6、CMS收集器

 
CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。CMS收集器是基于“标记-清除”算法实现的,它的运作过程分为4个步骤:
 
1)初始标记(CMS initial mark)
2)并发标记(CMS concurrent mark)
3)重新标记(CMS remark)
4)并发清除(CMS concurrent sweep)
 
其中,初始标记和重新标记这两个步骤仍然需要“Stop the World”(停止工作线程)。初始标记仅仅只是标记一下GC Roots能直接关联到的对象,速度很快。并发标记阶段就是进行GC Roots Tracing的过程,而重新标记阶段则是为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短。
 

 

七、G1(Garbage-First)收集器

G1(Garbage-First)收集器是一款面向服务端应用的垃圾收集器。如果不计算维护Remembered Set的操作,G1收集器的运作大致可以分为以下几个步骤:
1)初始标记(Initial Marking)
2)并发标记(Concurrent Marking)
3)最终标记(Final Marking)
4)筛选回收(Live Data Counting and Evacuation)
 

 
 

想买保时捷的运维李先生学Java性能之 垃圾收集器的更多相关文章

  1. 想买保时捷的运维李先生学Java性能之 垃圾收集算法

    前言 从原来只知道-Xms.-Xmx是设置内存的,到现在稍微理解了一些堆内存等Java虚拟机的一些知识.明白了技术这一个东西还是得要有输入才能实践,原理与实践要相辅相成,后续把JVM的监控好好总结一下 ...

  2. 想买保时捷的运维李先生学Java性能之 运行时数据区域

    前言 不知道自己不知道,不知道自己知道,知道自己不知道,知道自己知道,目前处于知道自己不知道这个阶段,很痛苦啊,干了4年了运维,是一个坎.越来越发觉想要走得远,还是得扎根底.   一.运行时数据区域 ...

  3. 想买保时捷的运维李先生学Java性能之 生存与毁灭

    一.判断对象是否存活     1.引用计数算法   给对象中添加一个引用计数器,每当有一个地方引用它时,计数器就加1:当引用失效时,计数器的值就减1:任何时刻计数器为0的对象是不可能再被使用的.引用计 ...

  4. 想买保时捷的运维李先生学Java性能之 JIT即时编译器

    前言 本文记录日常学习<深入理解Java虚拟机>,不知道为啥感觉看一遍也就过了,喜欢动动手理解理解,这样才有点感觉,静不下心来的时候,看书抄书也可以用这个办法. 一.什么是JIT(Just ...

  5. Linux运维不可不知的性能监控和调试工具

    Linux运维不可不知的性能监控和调试工具 1 nagios Nagios是一个开源监控解决方案,我觉得他可以监控一切 ,可以看一下我以前的文章:NAGIOS 2 ps #用来查看程序的运行情况 ps ...

  6. Python_oldboy_自动化运维之路_函数,装饰器,模块,包(六)

    本节内容 上节内容回顾(函数) 装饰器 模块 包 1.上节内容回顾(函数) 函数 1.为什么要用函数? 使用函数之模块化程序设计,定义一个函数就相当于定义了一个工具,需要用的话直接拿过来调用.不使用模 ...

  7. 从零开始学 Java - Spring AOP 拦截器的基本实现

    一个程序猿在梦中解决的 Bug 没有人是不做梦的,在所有梦的排行中,白日梦最令人伤感.不知道身为程序猿的大家,有没有睡了一觉,然后在梦中把睡之前代码中怎么也搞不定的 Bug 给解决的经历?反正我是有过 ...

  8. 从零起步做到Linux运维经理, 你必须管好的23个细节

    “不想成为将军的士兵,不是好士兵”-拿破仑 如何成为运维经理? 一般来说,运维经理大概有两种出身:一种是从底层最基础的维护做起,通过出色的维护工作,让公司领导对这个人非常认可,同时对Linux运维工作 ...

  9. 从零起步做到Linux运维经理,你必须管好的23个细节

    不想成为将军的士兵,不是好士兵-拿破仑 如何成为运维经理?成为运维经理需要什么样的能力?我想很多运维工程师都会有这样的思考和问题. 如何成为运维经理.一般来说,运维经理大概有两种出身,一种是从底层最基 ...

随机推荐

  1. 从四个问题透析Linux下C++编译&链接

    摘要:编译&链接对C&C++程序员既熟悉又陌生,熟悉在于每份代码都要经历编译&链接过程,陌生在于大部分人并不会刻意关注编译&链接的原理.本文通过开发过程中碰到的四个典型 ...

  2. JAVA基础之代码简洁之道

    引言 普通的工程师堆砌代码,优秀的工程师优雅代码,卓越的工程师简化代码.如何写出优雅整洁易懂的代码是一门学问,也是软件工程实践里重要的一环.--来自网络 背景 软件质量,不但依赖于架构及项目管理,更与 ...

  3. Django 联合唯一UniqueConstraint

    from django.db import models class UserAttention(models.Model): watcher = models.ForeignKey('user.Us ...

  4. python中numpy.savetxt 参数

    转载:https://blog.csdn.net/qq_36535820/article/details/99543188 numpy.savetxt 参数 numpy.savetxt(fname,X ...

  5. STM32之旅4——USART

    STM32之旅4--USART 串口也是用的比较多的,在STM32CubeMX中生成代码后,需要添加一些代码才可以用. drv_usart.h: #ifndef __DRV_USART_H #defi ...

  6. 执行新增和修改操作报错connection is read-only. Queries leading to data modification are not allowed

    出现这个问题的原因是默认事务只有只读权限,因此要添加下面的每一个add*,del*,update*等等. 分别给予访问数据库的权限. 方法名的前缀有该关键字设置了read-only=true,将其改为 ...

  7. CentOS7 下 swap 分区的创建、删除及相关配置

    一般我们在购买云服务器(例如:阿里云ECS.腾讯云服务器)的时候,选择 CentOS 7 系统之后,登录系统,发现 swap 大小为 0(即没有分配). 如果我们想在该 服务器上安装 Oracle 数 ...

  8. 用ip xfrm搭ipsec隧道

    拓扑如下 基本的IP配置就不说了,直接写重点,在LS上配置 #配置SA ip xfrm state add src 194.168.10.4 dst 194.168.10.5 proto esp sp ...

  9. Javascript判断数据类型的五种方式及其特殊性

    Javascript判断数据类型的五种方式及区别 @ 目录 typeof instanceof Object.prototype.toString isArray iisNaN ----------- ...

  10. 《Kafka笔记》2、环境搭建、Topic管理

    目录 一.Kafka环境搭建和Topic管理 1 单机环境搭建 1.1 环境准备 1.1.1 JDK 安装 1.1.2 配置主机名和ip 1.1.3 关闭防火墙和防火墙开机自启动 1.1.4 zook ...