什么是 Java 垃圾回收器

Java 垃圾回收器是 Java 虚拟机 (JVM) 的三个重要模块 (另外两个是解释器和多线程机制) 之一,为应用程序提供内存的自动分配 (Memory Allocation)、自动回收 (Garbage Collect) 功能,这两个操作都发生在 Java 堆上 (一段内存快)。某一个时点,一个对象如果有一个以上的引用 (Rreference) 指向它,那么该对象就为活着的 (Live),否则死亡 (Dead),视为垃圾,可被垃圾回收器回收再利用。垃圾回收操作需要消耗 CPU、线程、时间等资源,所以容易理解的是垃圾回收操作不是实时的发生 (对象死亡马上释放),当内存消耗完或者是达到某一个指标 (Threshold, 使用内存占总内存的比列,比如 0.75) 时,触发垃圾回收操作。有一个对象死亡的例外,java.lang.Thread 类型的对象即使没有引用,只要线程还在运行,就不会被回收。

回收的机制

依据统计分析可知,Java (包括一些其它高级语言) 里面大多数对象生命周期都是短暂的,所以把 Java 内存分代管理。分代的目的无非就是为不同代的内存块运用不同的管理策略 (算法),从而最大化性能。相对于年老代,通常年轻代要小很多,回收的频率高,速度快。年老代则回收频率低,耗时长。内存在年轻代里面分配,年轻代里面的对象经过多个回收周期依然存活的会自动晋升到年老代。

设计选型 (Design Choices)

设计选型影响 JVM 垃圾回收器的实现难度,以及 JVM 的性能指标,适用于不同的场景。描述的是回收算法的风格特点。

单线程串行回收 VS 多线程并行回收

回收操作自身是否多线程处理的问题。单线程回收的优点是简单,易实现,碎片少,适用于单核的机器。多线程并行回收在多核机器上面可以充分的利用 CPU 资源,减少回收的时间,增加生产力,缺点是复杂且可能有部分碎片没有回收。

回收时暂停应用线程 VS 回收和应用并发进行

回收操作时是否暂停应用线程的问题。暂停应用线程的优点是简单、准确、清理得比较干净、清理的时间也短 (CPU 资源独占),缺点是暂停应用线程之后会造成垃圾回收周期内应用的回应时间拉长,实时性非常高的系统比较敏感。回收和应用线程并行处理的优点是应用反应时间比较平稳、缺点是实现难度大、清理频率高、可能有碎片。

不合并释放的内存片段 VS 合并释放的内存片段 VS 把活着的复制到新的地方

这三个选型描述的是如何管理死亡的内存块片段。死亡的内存片段通常散落在堆的各个地方,如果不加以管理会有两个问题,内存分配的时候因查找可用的内存而导致速度慢,小的碎片会导致内存的浪费 (比如大的数组要求大的连续内存片段)。管理有两种方式,把活着的内存挪到内存块的某一端,记录可用内存的开始位置,或者干脆把活着的内存复制到一个新的内存区域,原来的内存块整个空出来。

性能指标 (Performance Metrics)

  • 生产率 (Throughput)
    一个较长的周期 (长的周期才有意义) 内,非回收时间占总时间的比率。度量系统的运行效率。

  • 垃圾回收花费 (Garbage Collection overhead)
    一个较长的周期内,回收时间占总时间的比率。与生产率相对应,加起来为 100%。

  • 暂停时间间隔 (Pause time)
    Java 虚拟机在回收垃圾的时候,有的算法会暂停所有应用线程的执行,某些系统可能对暂停的时间间隔比较敏感。

  • 回收的频率 (Frequency of collection)
    平均多久会发生回收操作。

  • 内存占用的大小 (Footprint)
    如堆的大小。

  • 实时性 (Promptness)
    自一个对象死亡起,经过多久该对象所占用内存被回收。

垃圾回收的类型

所有的回收器类型都是基于分代技术。Java HotSpot 虚拟机包含三代,年轻代 (Young Generation)、年老代 (Old Generation)、永久代 (Permanent Generation)。

  • 永久代
    存储类、方法以及它们的描述信息。可以通过 -XX:PermSize=64m 和 -XX:MaxPermSize=128m 两个可选项指定初始大小和最大值。通常 我们不需要调节该参数,默认的永久代大小足够了,不过如果加载的类非常多,不够用了,调节最大值即可。

  • 年老代 
    主要存储年轻代中经过多个回收周期仍然存活从而升级的对象,当然对于一些大的内存分配,可能也直接分配到永久代 (一个极端的例子是年轻代根本就存不下)。

  • 年轻代
    绝大多数的内存分配回收动作都发生在年轻代。如下图所示,年轻代被划分为三个区域,原始区 (Eden) 和两个小的存活区 (Survivor),两个存活区按功能分为 From 和 To。绝大多数的对象都在原始区分配,超过一个垃圾回收操作仍然存活的对象放到存活区。

串行回收器 (Serial Collector)

单线程执行回收操作,回收期间暂停所有应用线程的执行,client 模式下的默认回收器,通过 -XX:+UseSerialGC 命令行可选项强制指定。

  • 年轻代的回收算法 (Minor Collection)
    把 Eden 区的存活对象移到 To 区,To 区装不下直接移到年老代,把 From 区的移到 To 区,To 区装不下直接移到年老代,From 区里面年龄很大的升级到年老代。 回收结束之后,Eden 和 From 区都为空,此时把 From 和 To 的功能互换,From 变 To,To 变 From,每一轮回收之前 To 都是空的。设计的选型为复制。

  • 年老代的回收算法 (Full Collection)
    年老代的回收分为三个步骤,标记 (Mark)、清除 (Sweep)、合并 (Compact)。标记阶段把所有存活的对象标记出来,清除阶段释放所有死亡的对象,合并阶段 把所有活着的对象合并到年老代的前部分,把空闲的片段都留到后面。设计的选型为合并,减少内存的碎片。

并行回收器 (Parallel Collector)

使用多个线程同时进行垃圾回收,多核环境里面可以充分的利用 CPU 资源,减少回收时间,增加 JVM 生产率,Server 模式下的默认回收器。与串行回收器相同,回收期间暂停所有应用线程的执行。通过 -XX:+UseParallelGC 命令行可选项强制指定。

  • 年轻代的回收算法 (Minor Collection)
    使用多个线程回收垃圾,每一个线程的算法与串行回收器相同。

  • 年老代的回收算法 (Full Collection)
    年老代依然是单线程的,与串行回收器相同。

并行合并收集器 (Parallel Compacting Collection)

年轻代和年老代的回收都是用多线程处理。通过命令可选项 -XX:+UseParallelOldGC 指定,–XX:ParallelGCThreads=3 还可进一步指定参与并行回收的线程数。与串行回收器相同,回收期间暂停所有应用线程的执行。与并行回收器相比,年老代的回收时间更短,从而减少了暂停时间间隔 (Pause time)。通过–XX:+UseParallelOldGC 命令行可选项强制指定。

  • 年轻代的回收算法 (Minor Collection)
    与并行回收器 (Parallel Collector) 相同

  • 年老代的回收算法 (Full Collection) 
    年老代分为三个步骤,标记、统计、合并。这里用到分的思想,把年老代划分为很多个固定大小的区 (region)。 标记阶段,把所有存活的对象划分为 N 组 (应该与回收线程数相同),每一个线程独立的负责自己那一组,标记存活对象的位置以及 所在区 (Region) 的存活率信息,标记为并行的。统计阶段,统计每一个区 (Region) 的存活率,原则上靠前面的存活率较高,从前到后, 找到值得合并的开始位置 (绝大多数对象都存活的区不值得合并),统计阶段是串行的 (单线程)。合并阶段,依据统计阶段的信息,多线程 并行的把存活的对象从一个区 (Region) 复制到另外一个区 (Region)。

并发标记清除回收器 (Concurrent Mark-Sweep Collector)

又名低延时收集器 (Low-latency Collector),通过各种手段使得应用程序被挂起的时间最短。基本与应用程序并发地执行回收操作,没有合并和复制操作。通过命令行 -XX:+UseConcMarkSweepGC 指定,在单核或者双核系统里面还可以指定使用增量式回收模式 -XX:+UseConcMarkSweepGC。增量式回收是指把回收操作分为多个片段,执行一个片段之后释放 CPU 资源给应用程序,未来的某个时点接着上次的结果继续回收下去。目的也是减少延时。

  • 年轻代的回收算法 (Minor Collection)
    与并行回收器 (Parallel Collector) 相同

  • 年老代的回收算法 (Full Collection) 
    分为四个步骤,初始标记 (Initial Mark)、并发标记 (Concurrent Mark)、再次标记 (Remark)、以及并发清理 (Concurrent Sweep)。特别注意,没有合并操作,所以会有碎片。

  • 初始化阶段:暂停应用线程,找出所有存活的对象,耗时比较短,回收器使用单线程。

  • 并发标记阶段:回收器标记操作与应用并发运行,回收器使用单线程标记存活对象。

  • 再次标记:并发标记阶段由于应用程序也在运行,这个过程中可能新增或者修改对象。所以再次暂停应用线程,找出所有修改的对象,使用多线程标记。

  • 并发清理:回收器清理操作与应用并发运行,回收器使用单线程清理死亡对象。

Java 垃圾回收器的性能评估工具

  • –XX:+PrintGCDetails 和–XX:+PrintGCTimeStamps
    垃圾回收的开始时间,持续时间,每一代的空余内存等信息。

  • jmap [options] pid
    jamp 2043 查看 2043 进程里面已经加载的共享对象。通常 DLL 文件。
    jmap -heap 2043 查看内存堆的配置信息以及使用情况。
    jmap -permstat 2043 查看永久代的加载情况。
    jmap -histo 2043 查看类的加载和内存占用情况。

  • jstat [options] pid
    jstat -class 2043 class 加载、卸载、内存占用情况。
    jstat -gc 2043 GC 执行情况。

后记

Java 提供自动选择和自动性能优化功能。在做垃圾回收器调优之前,先列出所关注的性能指标,通过命令行告诉 JVM 你所关注的性能指标,由 JVM 自动调优,如果不满意,可以指定垃圾回收器。OutOfMemory 通常是由于堆内存不足,调节 -Xmx1024m 和 -XX:MaxPermSize=128m 命令行可选项即可。

IDEA 保姆级安装教程:  http://note.youdao.com/s/Wq2GSETJ  

计算机专业常用毕业设计集合:  http://note.youdao.com/s/PIJHOqnk  

什么是 Java 垃圾回收器~相关推荐

  1. JAVA垃圾回收器的介绍

    JAVA垃圾回收器的介绍 垃圾回收器一共有7种: 如下图 其中G1 和 CMS 属于比较新的,暂停时间比之前较少. serial serial Old parNew 这个是serial的多线程版本. ...

  2. 关于java垃圾回收器(GC)的一些基础知识

    关于java垃圾回收器(GC)的一些基础知识 定义: Java的垃圾回收机制是Java虚拟机提供的能力,用于在空闲时间以不定时的方式动态回收无任何引用的对象占据的内存空间. 注意:回收的是已经不再被使 ...

  3. Java垃圾回收器的工作原理

    上课,老师照本宣科,实在难以理解,干脆就看书包里的Java书,正好看了Java的垃圾回收器是如何工作的,觉得有必要记录一下. 参考于 Java编程思想第四版(Thinking in Java) 老年代 ...

  4. java垃圾回收器有哪些_各种Java垃圾回收器的比较总结

    原标题:各种Java垃圾回收器的比较总结 现在已经是2017年了,但是对大多数开发人员而言有两件事情仍然是个谜--垃圾回收以及异性(码农又被嘲笑了).由于我对后者也不是特别了解,我想我还是试着说说前者 ...

  5. 深入理解Java虚拟机:Java垃圾回收器

    本篇内容包括:7 种 Jvm 垃圾回收器的介绍.对比 以及 对应的 Jvm 参数设置,这 7 种包括了:Serial.ParNew 以及 Parallel Scavenge 三种新生代回收器 和 :S ...

  6. 【不同的Java垃圾回收器的比较】

    现在已经是2014年了,但是对大多数开发人员而言有两件事情仍然是个谜--java垃圾回收以及异性(码农又被嘲笑了).由于我对后者也不是特别了解,我想我还是试着说说前者吧,尤其是随着Java8的到来,这 ...

  7. java8 垃圾 不同_【不同的Java垃圾回收器的比较】

    现在已经是2014年了,但是对大多数开发人员而言有两件事情仍然是个谜--java垃圾回收以及异性(码农又被嘲笑了).由于我对后者也不是特别了解,我想我还是试着说说前者吧,尤其是随着Java8的到来,这 ...

  8. JAVA垃圾回收器源码_浅谈关于Java的GC垃圾回收器的一些基本概念

    一.基本回收算法 1. 引用计数(Reference Counting) 比较古老的回收算法.原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数.垃圾回收时,只用收集计数为0的对象.此 ...

  9. java+垃圾回收器+的功能_JAVA-JVM 垃圾回收器

    分代收集:新生代(复制算法),老年代(标记清除,标记整理) . jps -v 可查看当前JVM 使用的是那种垃圾收集器 垃圾回收器又分单线程多线程,使用. 常见的垃圾回收器如下图:垃圾回收器的连线表示 ...

最新文章

  1. 第五周项目四-长方柱形(1)
  2. 设置VSS2005使支持通过Internet访问(转)
  3. java bat 运行 jar文件_运行bat文件启动java的jar且不弹出DOS窗口,后台运行java的jar包...
  4. 【NLP】ACL 2021中的25个Transformers模型
  5. 安卓布局工具---Hierarchy Viewer
  6. 有序数组求和问题(Two Sum II - Input array is sorted)
  7. springboot 控制台程序读取配置文件(原创)
  8. python游戏房间_Python House冒险-如果已经进入一个房间,如何给出不同的输出
  9. kafka基本概念和hello world搭建
  10. C#3.0入门系列(八)-之GroupBy操作
  11. 27.crontab
  12. angularJS 双向数据绑定、作用域、表达式、
  13. DOS命令教程 第二章——ping命令
  14. BitTorrent详解
  15. java基于ssm的学校教务管理系统的设计与实现论文
  16. 三年级计算机 键盘指法 教案,第13课 键盘指法练习
  17. Python培训得多少钱
  18. 知乎周源微信_每周源代码16-风管磁带版
  19. 手机与windows大文件高速传输方法 自用
  20. kestrel轻量级消息队列的安装

热门文章

  1. FATFS 的几个函数使用方法
  2. Android常用的工具类汇总(方便日后使用)
  3. C#根据输入的层数打印星号(*)组成的的三角形
  4. 使用Gradle构建项目
  5. 强化学习基础1.7 | 状态价值函数
  6. tortoisegit使用教程图文详解
  7. 一个好的界面设计应该注意的 75 个原则
  8. 计算机辅助设计简单作品,计算机辅助设计(范文).pdf
  9. django认证系统实现自定义权限管理的方法 - python
  10. Mind Control(暴力+枚举)