深入理解Java虚拟机之经典垃圾收集器

目录
  • 1. 综述
    • 1. 总述:
    • 2. 图示总述
    • 3. 应用中应如何做出选择?
  • 2. Serial收集器
    • 1. 简介
    • 2. 图解工作过程
    • 3.使用的垃圾收集算法
    • 4. 优点
    • 5. 缺点
    • 6. 主要应用场景
  • 3. ParNew收集器
    • 1. 简介
    • 2. 图解工作过程
    • 3. 使用的垃圾收集算法
    • 4. 补充概念
    • 5. 主要应用场景
  • 4. Parallel Scavenge收集器
    • 1. 简介
    • 2. 补充概念
    • 3. 图解工作过程
    • 4. 使用的垃圾收集算法
    • 5. 相关的参数
  • 5. Serial Old收集器
    • 1. 简介
    • 2. 图解工作过程
    • 3. 使用的垃圾收集算法
    • 4. 主要的应用场景
  • 6. Parallel Old收集器
    • 1. 简介
    • 2. 图解工作过程
    • 3. 使用的垃圾收集算法
    • 4. 主要的应用场景
  • 7. CMS收集器
    • 1. 简介
    • 2. 工作过程
    • 3. 图解工作过程
    • 4. 使用的垃圾收集算法
    • 5. 优点
    • 6. 缺点
    • 7. 主要的应用场景
  • 8. Garbage First收集器
    • 1. 简介
    • 2. 工作过程
    • 3. 图解工作过程
    • 4. 特点
    • 5. 使用此收集器下的堆内存说明
    • 6. 主要的应用场景

本文参考于《深入理解Java虚拟机》

1. 综述

1. 总述:

如果说收集算法是内存回收的方法论,那垃圾收集器就是内存回收的实践者。《Java虚拟机规范》中对垃圾收集器应该如何实现并没有做出任何规定,因此不同的厂商、不同版本的虚拟机所包含的垃圾收集器都可能会有很大差别,不同的虚拟机一般也都会提供各种参数供用户根据自己的应用特点和要求组合出各个内存分代所使用的收集器。

2. 图示总述

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

3. 应用中应如何做出选择?

虽然我们会对各个收集器进行比较,但并非为了挑选一个最好的收集器出来,虽然垃圾收集器的技术在不断进步,但直到现在还没有最好的收集器出现,更加不存在“万能”的收集器,所以我们选择的只是对具体应用最合适的收集器。这点不需要多加论述就能证明:如果有一种放之四海皆准、任何场景下都适用的完美收集器存在,HotSpot虚拟机完全没必要实现那么多种不同的收集器了。

2. Serial收集器

1. 简介

Serial收集器是最基础、历史最悠久的收集器,曾经(在JDK 1.3.1之前)是HotSpot虚拟机新生代收集器的唯一选择。大家只看名字就能够猜到,这个收集器是一个单线程工作的收集器,但它的“单线程”的意义并不仅仅是说明它只会使用一个处理器或一条收集线程去完成垃圾收集工作,更重要的是强调在它进行垃圾收集时,必须暂停其他所有工作线程,直到它收集结束(“Stop The World”)。

2. 图解工作过程

3.使用的垃圾收集算法

标记-复制算法

4. 优点

简单而高效(与其他收集器的单线程相比),对于内存资源受限的环境,它是所有收集器里额外内存消耗最小的;对于单核处理器或处理器核心数较少的环境来说,Serial收集器由于没有线程交互的开销,专心做垃圾收集自然可以获得最高的单线程收集效率

5. 缺点

在垃圾回收过程中会触发 “Stop The World” 而产生停顿,从而导致用户体验不好。

6. 主要应用场景

Serial收集器对于运行在客户端模式下的虚拟机来说是一个很好的选择。

3. ParNew收集器

1. 简介

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

2. 图解工作过程

3. 使用的垃圾收集算法

标记-复制算法

4. 补充概念

  • 并行:并行描述的是多条垃圾收集器线程之间的关系,说明同一时间有多条这样的线程在协同工作,通常默认此时用户线程是处于等待状态。
  • 并发:并发描述的是垃圾收集器线程与用户线程之间的关系,说明同一时间垃圾收集器线程与用户线程都在运行。由于用户线程并未被冻结,所以程序仍然能响应服务请求,但由于垃圾收集器线程占用了一部分系统资源,此时应用程序的处理的吞吐量将受到一定影响。

5. 主要应用场景

它是许多运行在 Server 模式下的虚拟机的首要选择,除了 Serial 收集器外,只有它能与 CMS 收集器(真正意义上的并发收集器,后面会介绍到)配合工作。

4. Parallel Scavenge收集器

1. 简介

Parallel Scavenge收集器也是一款新生代收集器,它同样是基于标记-复制算法实现的收集器,也是能够并行收集的多线程收集器。Parallel Scavenge的诸多特性从表面上看和ParNew非常相似。Parallel Scavenge收集器的特点是它的关注点与其他收集器不同,CMS等收集器的关注点是尽可能地缩短垃圾收集时用户线程的停顿时间,而Parallel Scavenge收集器的目标则是达到一个可控制的吞吐量

2. 补充概念

吞吐量就是处理器用于运行用户代码的时间与处理器总消耗时间的比值

如果虚拟机完成某个任务,用户代码加上垃圾收集总共耗费了100分钟,其中垃圾收集花掉1分钟,那吞吐量就是99%。 停顿时间越短就越适合需要与用户交互或需要保证服务响应质量的程序,良好的响应速度能提升用户体验;而高吞吐量则可以最高效率地利用处理器资源,尽快完成程序的运算任务,主要适合在后台运算而不需要太多交互的分析任务

3. 图解工作过程

4. 使用的垃圾收集算法

标记-复制算法

5. 相关的参数

Parallel Scavenge收集器提供了两个参数用于精确控制吞吐量,分别是控制最大垃圾收集停顿时间的 -XX:MaxGCPauseMillis 参数以及直接设置吞吐量大小的 -XX:GCTimeRatio 参数。

5. Serial Old收集器

1. 简介

Serial Old是Serial收集器的老年代版本,它同样是一个单线程收集器,使用标记-整理算法。

2. 图解工作过程

3. 使用的垃圾收集算法

标记-整理算法

4. 主要的应用场景

  • 供客户端模式下的HotSpot虚拟机使用
  • 在服务端模式下,一种在JDK 5以及之前的版本中与Parallel Scavenge收集器搭配使用;另外一种就是作为CMS收集器发生失败时的后备预案

6. Parallel Old收集器

1. 简介

Parallel Old是Parallel Scavenge收集器的老年代版本,支持多线程并发收集,基于标记-整理算法实现。

2. 图解工作过程

3. 使用的垃圾收集算法

标记-整理算法

4. 主要的应用场景

注重吞吐量或者处理器资源较为稀缺的场合,都可以优先考虑Parallel Scavenge 加 Parallel Old收集器这个组合。

7. CMS收集器

1. 简介

CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。CMS收集器是基于标记-清除算法实现的。它非常适合在注重用户体验的应用上使用

2. 工作过程

  • 初始标记:标记一下GC Roots能直接关联到的对象,速度很快
  • 并发标记:从GC Roots的直接关联对象开始遍历整个对象图的过程,这个过程耗时较长但是不需要停顿用户线程用户线程可以与垃圾收集线程一起并发运行。
  • 重新标记:为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间通常会比初始标记阶段稍长一些,但也远比并发标记阶段的时间短。
  • 并发清除:清理删除掉标记阶段判断的已经死亡的对象,由于不需要移动存活对象,所以这个阶段也是可以与用户线程同时并发的。

3. 图解工作过程

4. 使用的垃圾收集算法

标记-清除算法

5. 优点

  • 回收停顿时间短,给用户带来良好的交互体验。
  • 并发收集

6. 缺点

  • 对处理器资源非常敏感
  • 无法处理“浮动垃圾”
  • 因为CMS收集器是一款基于标记-清除算法的垃圾收集器,其收集结束时会有大量空间碎片产生

7. 主要的应用场景

它非常适合在注重用户体验和要求停顿时间短的应用上使用

8. Garbage First收集器

1. 简介

G1 (Garbage-First) 是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器。以极高概率满足 GC 停顿时间要求的同时,还具备高吞吐量性能特征。G1在后台维护一个优先级列表,每次根据用户设定允许的收集停顿时间,优先处理回收价值收益最大的那些Region。这种使用 Region划分内存空间以及有优先级的区域回收方式,保证了 G1 收集器在有限时间内可以尽可能高的收集效率(把内存化整为零)。

2. 工作过程

  • 初始标记:仅仅只是标记一下GC Roots能直接关联到的对象,并且修改TAMS指针的值,让下一阶段用户线程并发运行时,能正确地在可用的Region中分配新对象。这个阶段需要停顿线程,但耗时很短,而且是借用进行Minor GC的时候同步完成的,所以G1收集器在这个阶段实际并没有额外的停顿。
  • 并发标记:从GC Root开始对堆中对象进行可达性分析,递归扫描整个堆里的对象图,找出要回收的对象,这阶段耗时较长,但可与用户程序并发执行。当对象图扫描完成以后,还要重新处理SATB记录下的在并发时有引用变动的对象。最终标记:对用户线程做另一个短暂的暂停,用于处理并发阶段结束后仍遗留下来的最后那少量的SATB记录
  • 筛选回收:负责更新Region的统计数据,对各个Region的回收价值和成本进行排序,根据用户所期望的停顿时间来制定回收计划,可以自由选择任意多个Region构成回收集,然后把决定回收的那一部分Region的存活对象复制到空的Region中再清理掉整个旧Region的全部空间。这里的操作涉及存活对象的移动,是必须暂停用户线程,由多条收集器线程并行完成的。

从上述阶段的描述可以看出,G1收集器除了并发标记外,其余阶段也是要完全暂停用户线程的,换言之,它并非纯粹地追求低延迟,官方给它设定的目标是在延迟可控的情况下获得尽可能高的吞吐量,所以才能担当起“全功能收集器”的重任与期望。

3. 图解工作过程

4. 特点

  • 并行与并发:
  • 分代收集
  • 空间整合
  • 可预测的停顿

5. 使用此收集器下的堆内存说明

G1不再坚持固定大小以及固定数量的分代区域划分,而是把连续的Java堆划分为多个大小相等的独立区域(Region),每一个Region都可以根据需要,扮演新生代的Eden空间、Survivor空间,或者老年代空间。收集器能够对扮演不同角色的Region采用不同的策略去处理,这样无论是新创建的对象还是已经存活了一段时间、熬过多次收集的旧对象都能获取很好的收集效果。Region中还有一类特殊的Humongous区域(H),专门用来存储大对象。G1认为只要大小超过了一个Region容量一半的对象即可判定为大对象。每个Region的大小可以通过参数-XX:G1HeapRegionSize设定,取值范围为1MB~32MB,且应为2的N次幂。而对于那些超过了整个Region容量的超级大对象将会被存放在N个连续的Humongous Region之中,G1的大多数行为都把Humongous Region作为老年代的一部分来进行看待,如上图所示。虽然G1仍然保留新生代和老年代的概念,但新生代和老年代不再是固定的了,它们都是一系列区域(不需要连续)的动态集合

6. 主要的应用场景

主要使用于服务端模式下的垃圾回收

到此这篇关于深入理解Java虚拟机之经典垃圾收集器的文章就介绍到这了,更多相关java垃圾收集器内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • JAVA垃圾收集器与内存分配策略详解

    引言 垃圾收集技术并不是Java语言首创的,1960年诞生于MIT的Lisp是第一门真正使用内存动态分配和垃圾收集技术的语言.垃圾收集技术需要考虑的三个问题是: 1.哪些内存需要回收 2.什么时候回收 3.如何回收 java内存运行时区域的分布,其中程序计数器,虚拟机栈,本地方法区都是随着线程而生,随线程而灭,所以这几个区域就不需要过多考虑回收问题.但是堆和方法区就不一样了,只有在程序运行期间我们才知道会创建哪些对象,这部分内存的分配和回收都是动态的.垃圾收集器所关注的就是这部分内存. 一 对象

  • 详解java中jvm虚拟机栈的作用

    jvm虚拟机栈的作用 jvm虚拟机栈栈帧的组成 jvm虚拟机栈,也叫java栈,它由一个个的栈帧组成,而栈帖由以下几个部分组成 局部变量表-存储方法参数,内部使用的变量 操作数栈-在变量进行存储时,需要进行入栈和出栈 动态连接-引用类型的指针 方法出口-方法的返回 一段原程序代码 package com.lind.basic; public class Demo1 { static int hello() { int a = 1; int b = 2; int c = a + b; return

  • java虚拟机创建失败的原因整理

    创建java虚拟机失败的解决方法 解决问题的步骤: 1.从eclipse文件夹中打开eclipse.ini文件 2.修改–launcher.XXMaxPermSize属性 3.将值改为512m即可 配置文件格式: -startup plugins/org.eclipse.equinox.launcher_1.3.0.v20120522-1813.jar --launcher.library plugins/org.eclipse.equinox.launcher.win32.win32.x86_

  • Java虚拟机使用jvisualvm工具远程监控tomcat内存

    jdk中自带了很多工具可以用于性能分析,位于jdk的bin目录下,jvisualvm工具可以以图形化的方式更加直观的监控本地以及远程的java进程的内存占用,线程状态等信息. 一.配置tomcat 在tomcat的catalina.sh文件开头加上如下配置: JAVA_OPTS="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.ssl=fa

  • 深入理解Java虚拟机之经典垃圾收集器

    目录 1. 综述 1. 总述: 2. 图示总述 3. 应用中应如何做出选择? 2. Serial收集器 1. 简介 2. 图解工作过程 3.使用的垃圾收集算法 4. 优点 5. 缺点 6. 主要应用场景 3. ParNew收集器 1. 简介 2. 图解工作过程 3. 使用的垃圾收集算法 4. 补充概念 5. 主要应用场景 4. Parallel Scavenge收集器 1. 简介 2. 补充概念 3. 图解工作过程 4. 使用的垃圾收集算法 5. 相关的参数 5. Serial Old收集器 1

  • 深入理解Java虚拟机_动力节点Java学院整理

    什么是Java虚拟机 Java程序必须在虚拟机上运行.那么虚拟机到底是什么呢?先看网上搜索到的比较靠谱的解释: 虚拟机是一种抽象化的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现的.Java虚拟机有自己完善的硬体架构,如处理器.堆栈.寄存器等,还具有相应的指令系统.JVM屏蔽了与具体操作系统平台相关的信息,使得Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行. 这种解释应该算是正确的,但是只描述了虚拟机的外部行为和功能,并没有针对内部原理

  • 深入理解Java虚拟机体系结构

    1概述 众所周知,Java支持平台无关性.安全性和网络移动性.而Java平台由Java虚拟机和Java核心类所构成,它为纯Java程序提供了统一的编程接口,而不管下层操作系统是什么.正是得益于Java虚拟机,它号称的"一次编译,到处运行"才能有所保障. 1.1Java程序执行流程 Java程序的执行依赖于编译环境和运行环境.源码代码转变成可执行的机器代码,由下面的流程完成: Java技术的核心就是Java虚拟机,因为所有的Java程序都在虚拟机上运行.Java程序的运行需要Java虚拟

  • 深入理解Java虚拟机 JVM 内存结构

    目录 前言 JVM是什么 JVM内存结构概览 运行时数据区 程序计数器 Java虚拟机栈 本地方法栈 方法区 运行时常量池 Java堆 直接内存 前言 JVM是Java中比较难理解和掌握的一部分,也是面试中被问的比较多的,掌握好JVM底层原理有助于我们在开发中写出效率更高的代码,可以让我们面对OutOfMemoryError时不再一脸懵逼,可以用掌握的JVM知识去查找分析问题.去进行JVM的调优.去让我们的应用程序可以支持更高的并发量等......总之一句话,学好JVM很重要! JVM是什么 J

  • 深入理解java虚拟机的故障处理工具

    前言 本文主要给大家介绍的是java虚拟机的故障处理工具,文中提到这些工具包括: 名称 主要作用 jps JVM process Status Tool, 显示指定系统内所有的HotSpot虚拟机进程.通常是本地主机 jstat JVM Statistics Monitoring Tool,用于收集HotSpot虚拟机各方面的运行数据 jinfo Configuration Info for java, 显示虚拟机配置信息 jmap Memory Map for Java, 生成虚拟机的内存存储

  • 解析Java虚拟机中类的初始化及加载器的父委托机制

    类的初始化 在初始化阶段,Java虚拟机执行类的初始化语句,为类的静态变量赋予初始值. 在程序中,静态变量的初始化有两种途径: 1.在静态变量的声明处进行初始化: 2.在静态代码块中进行初始化. 没有经过显式初始化的静态变量将原有的值. 一个比较奇怪的例子: package com.mengdd.classloader; class Singleton { // private static Singleton mInstance = new Singleton();// 位置1 // 位置1输

  • Java虚拟机内存分配与回收策略问题精细解读

    本文参考于<深入理解Java虚拟机> 内存分配与回收策略 Java技术体系的自动内存管理,最根本的目标是自动化地解决两个问题:自动给对象分配内存以及自动回收分配给对象的内存. 1. 综述 对象的内存分配,从概念上讲,应该都是在堆上分配(而实际上也有可能经过即时编译后被拆散为标量类型并间接地在栈上分配).在经典分代的设计下,新生对象通常会分配在新生代中,少数情况下(例如对象大小超过一定阈值)也可能会直接分配在老年代.对象分配的规则并不是固定的,<Java虚拟机规范>并未规定新对象的创

  • java 虚拟机深入了解

    什么是Java虚拟机 作为一个Java程序员,我们每天都在写Java代码,我们写的代码都是在一个叫做Java虚拟机的东西上执行的.但是如果要问什么是虚拟机,恐怕很多人就会模棱两可了.在本文中,我会写下我对虚拟机的理解.因为能力所限,可能有些地方描述的不够欠当.如果你有不同的理解,欢迎交流. 我们都知道Java程序必须在虚拟机上运行.那么虚拟机到底是什么呢?先看网上搜索到的比较靠谱的解释: 虚拟机是一种抽象化的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现的.Java虚拟机有自己完善的硬

  • Java虚拟机内存区域划分详解

    在谈 JVM 内存区域划分之前,我们先来看一下 Java 程序的具体执行过程,我画了一幅图. Java 源代码文件经过编译器编译后生成字节码文件,然后交给 JVM 的类加载器,加载完毕后,交给执行引擎执行.在整个执行的过程中,JVM 会用一块空间来存储程序执行期间需要用到的数据,这块空间一般被称为运行时数据区,也就是常说的 JVM 内存. 所以,当我们在谈 JVM 内存区域划分的时候,其实谈的就是这块空间--运行时数据区. 大家应该对官方出品的<Java 虚拟机规范>有所了解吧?了解这个规范可

  • 如何查看JVM使用的默认的垃圾收集器

    查看JVM使用的默认的垃圾收集器 查看步骤 cmd执行命令: java -XX:+PrintCommandLineFlags -version 输出如下(举例): 针对上述的-XX:UseParallelGC,这边我们引用<深入理解Java虚拟机:JVM高级特性与最佳实践>的介绍: 也就是说,打开此开关,使用的垃圾收集器是:新生代(Parallel Scavenge),老年代(Ps MarkSweep)组合. jvm默认垃圾收集器789 jdk1.7 默认垃圾收集器Parallel Scave

随机推荐