jvm(5)---垃圾回收(回收算法和垃圾收集器)

1.垃圾回收算法

1.1 标记-清除算法

算法分为“标记”和“清除”阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。它是最基础的收集算法,效率也很高,但是会带来两个明显的问题:

1.效率问题

2.空间问题,标记清除后会产生大量不连续的碎片

1.2 复制算法

为了解决效率问题,“复制”收集算法出现了。它可以将内存分为大小相同的两块,每次使用其中的一块。当这一块的内存使用完后,就将还存活的对象复制到另一块去,然后再把使用的空间一次清理掉。这样就使每次的内存回收都是对内存区间的一半进行回收。

1.3 标记-整理算法

根据老年代的特点特出的一种标记算法,标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象回收,而是让所有存活的对象向一段移动,然后直接清理掉端边界以外的内存。

1.4 分代收集算法

当前虚拟机的垃圾收集都采用分代收集算法,是根据对象存活周期的不同将内存分为几块。一般将java堆分为新生代和老年代,这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。

比如在新生代中,每次收集都会有大量对象死去,所以可以选择复制算法,只需要付出少量对象的复制成本就可以完成每次垃圾收集。而老年代的对象存活几率是比较高的,而且没有额外的空间对它进行分配担保,所以我们必须选择“标记-清除”或“标记-整理”算法进行垃圾收集。

2.垃圾收集器

回收算法是方法论,收集器就是具体的实现

2.1 Serial收集器

Serial(串行)收集器收集器是最基本、历史最悠久的垃圾收集器了。大家看名字就知道这个收集器是一个单线程收集器了。它的 “单线程” 的意义不仅仅意味着它只会使用一条垃圾收集线程去完成垃圾收集工作,更重要的是它在进行垃圾收集工作的时候必须暂停其他所有的工作线程( "Stop The World" ),直到它收集结束。新生代采用复制算法,老年代采用标记-整理算法。但是它简单而高效(与其他收集器的单线程相比)。Serial收集器由于没有线程交互的开销,自然可以获得很高的单线程收集效率。

----------

2.2 ParNew收集器

ParNew收集器其实就是Serial收集器的多线程版本。

----------

2.3 Parallel Scavenge收集器(1.8默认收集器)

Parallel Scavenge 收集器类似于ParNew 收集器,是Server 模式(内存大于2G,2个cpu)下的默认收集器

Parallel Scavenge收集器关注点是吞吐量(高效率的利用CPU)。CMS等垃圾收集器的关注点更多的是用户线程的停顿时间(提高用户体验)。所谓吞吐量就是CPU中用于运行用户代码的时间与CPU总消耗时间的比值。 Parallel Scavenge收集器提供了很多参数供用户找到最合适的停顿时间或最大吞吐量。

新生代采用复制算法,老年代采用标记-整理算法。

----------

2.4.Serial Old收集器

Serial收集器的老年代版本,它同样是一个单线程收集器。

----------

2.5 Parallel Old收集器

Parallel Scavenge收集器的老年代版本。使用多线程和“标记-整理”算法。在注重吞吐量以及CPU资源的场合,都可以优先考虑 Parallel Scavenge收集器和Parallel Old收集器。

----------

2.6 CMS收集器(主要是old区使用)

CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。它而非常符合在注重用户体验的应用上使用,它是HotSpot虚拟机第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程(基本上)同时工作。

从名字中的Mark Sweep这两个词可以看出,CMS收集器是一种 标记-清除”算法实现的,它的运作过程相比于前面几种垃圾收集器来说更加复杂一些。整个过程分为四个步骤:

1.初始标记: 暂停所有的其他线程(STW),并记录下直接与GC Roots相连的对象,速度很快 ;

2.并发标记: 同时开启GC和用户线程,去记录可达对象。但在这个阶段结束,并不能保证包含当前所有的可达对象。因为用户线程可能会不断的更新引用域,所以GC线程无法保证可达性分析的实时性。所以这个算法里会跟踪记录这些发生引用更新的地方。

3.重新标记: 重新标记阶段就是为了修正并发标记期间因为用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段的时间稍长,远远比并发标记阶段时间短

4.并发清除: 开启用户线程,同时GC线程开始对未标记的区域做清扫。

主要优点:并发收集、低停顿。但是它有下面三个明显的缺点:

1对CPU资源敏感(会和服务抢资源);

2.无法处理浮动垃圾(在java业务程序线程与垃圾收集线程并发执行过程中又产生的垃圾,这种浮动垃圾只能等到下一次gc再清理了);

3.它使用的回收算法-“标记-清除”算法会导致收集结束时会有大量空间碎片产生。

CMS的相关参数

  1. -XX:+UseConcMarkSweepGC 启用cms
  2. -XX:ConcGCThreads:并发的GC线程数(并非STW时间,而是和应用线程一起执行的线程数)
  3. -XX:+UseCMSCompactAtFullCollection:FullGC之后做压缩(减少碎片)
  4. -XX:CMSFullGCsBeforeCompaction:多少次FullGC之后压缩一次(因压缩非常的消耗时间,所以不能每次FullGC都做)
  5. -XX:CMSInitiatingOccupancyFraction:触发FulGC条件(默认是92)
  6. -XX:+UseCMSInitiatingOccupancyOnly:是否动态调节
  7. -XX:+CMSScavengeBeforeRemark:FullGC之前先做YGC(一般这个参数是打开的)

2.7 G1收集器(1.9 默认收集器)

G1 (Garbage-First)是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器. 以极高概率满足GC停顿时间要求的同时,还具备高吞吐量性能特征.

G1对堆的划分有所不同,它将Java堆划分为多个大小相等的独立区域(Region),虽保留新生代和老年代的概念,但不再是物理隔阂了,它们都是(可以不连续)Region的集合。

分配大对象(直接进Humongous区,专门存放短期巨型对象,不用直接进老年代,避免Full GC的大量开销)不会因为无法找到连续空间而提前触发下一次GC。

G1特点

1.并行与并发:G1能充分利用CPU、多核环境下的硬件优势,使用多个CPU(CPU或者CPU核心)来缩短Stop-The-World停顿时间。部分其他收集器原本需要停顿Java线程来执行GC动作,G1收集器仍然可以通过并发的方式让java程序继续执行。

2.分代收集:虽然G1可以不需要其他收集器配合就能独立管理整个GC堆,但是还是保留了分代的概念。

3.空间整合:与CMS的“标记--清理”算法不同,G1从整体来看是基于“标记整理”算法实现的收集器;从局部上来看是基于“复制”算法实现的。

4.可预测的停顿:这是G1相对于CMS的另一个大优势,降低停顿时间是G1 和 CMS 共同的关注点,但G1 除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片段内完成垃圾收集。

G1收集器的运作大致分为以下几个步骤:

1.初始标记(initial mark,STW):在此阶段,G1 GC 对根进行标记。该阶段与常规的 (STW) 年轻代垃圾回收密切相关。

2.并发标记(Concurrent Marking):G1 GC 在整个堆中查找可访问的(存活的)对象。

3.最终标记(Remark,STW):该阶段是 STW 回收,帮助完成标记周期。

4.筛选回收(Cleanup,STW):筛选回收阶段首先对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿时间来制定回收计划,这个阶段其实也可以做到与用户程序一起并发执行,但是因为只回收一部分Region,时间是用户可控制的,而且停顿用户线程将大幅提高收集效率。

G1收集器在后台维护了一个优先列表,每次根据允许的收集时间,优先选择回收价值最大的Region(这也就是它的名字Garbage-First的由来)。这种使用Region划分内存空间以及有优先级的区域回收方式,保证了G1收集器在有限时间内可以尽可能高的收集效率。

原文地址:https://www.cnblogs.com/nijunyang/p/11109516.html

时间: 2024-11-07 12:41:44

jvm(5)---垃圾回收(回收算法和垃圾收集器)的相关文章

Java虚拟机四:垃圾回收算法与垃圾收集器

在Java运行时的几个数据区域中,程序计数器,虚拟机栈,本地方法栈3个区域随着线程而生,随线程而灭,因此这几个区域的内存分配和回收具有确定性,不需要过多考虑垃圾回收问题,因为方法结束或者线程结束时,内存就回收了.但是方法区和堆区不一样,一个接口或者实现类所需要的内存可能不一样,一个方法的多个分支需要的内存也可能不一样,只有程序运行时才能知道创建哪些对象,这部分内存的分配和回收是动态的. 在进行垃圾回收时候,首先需要判断哪些对象需要回收,这就涉及到回收算法的问题. 一.垃圾回收算法 1.标记-清除

JVM(十一),垃圾回收之老年代垃圾收集器

十一.垃圾回收之老年代垃圾收集器 1.Serial Old收集器(标记整理算法-单线程-Client模式下) 2.Paraller Old收集器(标记整理算法-多线程-) 3.CMS收集器(标记清除算法) 4.G1收集器(新生代,老年代都可以用) 原文地址:https://www.cnblogs.com/xzmxddx/p/10366914.html

JVM(五)-垃圾收集算法和垃圾收集器

一.垃圾收集算法 (1)标记-清除算法 "标记-清除"(Mark-Sweep)算法,如它的名字一样,算法分为"标记"和"清除"两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象.之所以说它是最基础的收集算法,是因为后续的收集算法都是基于这种思路并对其缺点进行改进而得到的. 它的主要缺点有两个:一个是效率问题,标记和清除过程的效率都不高:另外一个是空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致,

JVM理论:(二/3)垃圾收集算法、垃圾收集器

掌握三种垃圾算法,七种垃圾收集器,了解每种垃圾收集器使用的是哪种垃圾收集算法,以及关于SafePoint的知识点. 垃圾收集算法 1.标记-清除算法(Mark-Sweep) 先标记(如可达性算法)出所有需要回收的对象,标记完后再统一回收所有被标记的对象. 缺点:标记和清除过程的效率都不高,且清除后会产生大量不连续的内存碎片. 2.复制算法(Copying) 将可用内存划分为大小相等的两块,每次只使用其中的一块.当其中一块的内存用完了,就将还存活的对象复制到另一块内存上,然后再把已使用过的内存空间

J深入学习ava虚拟机之——垃圾收集算法与垃圾收集器

今天我们将一起学习Java虚拟机使用垃圾收集算法和常见的垃圾收集器.Java虚拟机内存区域的程序计数器.虚拟机栈和本地方法栈3个区域是随线程而生,随线程而灭:栈中的栈帧随着方法的进入和退出出栈和入栈.每一个栈帧中分配多少内存基本上是在类结构确定下来的时候就已知的,因此这个几个区域的内存分配和回收都具备确定性,在这几个区域就不需要过多考虑回收问题,因为方法结束或者线程结束时,内存自然就跟着回收了.而Java堆和方法区就不一样,一个接口中的多个类实现需要的内存可能不一样,一个方法中的多个分支需要的内

JVM垃圾回收算法和垃圾收集器笔记

概述 程序计数器,本地方法栈,虚拟机栈随线程而生,随线程而灭. Java堆和方法区则不一样,这部分内存分配和回收的都是动态的,垃圾收集器所关注的是这部分内存. 判断对象是否是垃圾的算法 JVM没有选用引用计数算法来管理内存,最主要的是引用计数很难解决对象之间相互循环引用的问题.JVM采用了可达性分析算法来判断对象是否能回收.用GC Roots对象作为起点,向下搜索,搜索走过的路劲称为引用链(reference chain),当对一个对象到GC Roots没有任何引用链时,则证明对象不可用的. 判

java垃圾回收算法和垃圾收集器

垃圾收集算法.垃圾回收算法.java垃圾收集器 目录1. 垃圾收集算法1)引用计数法2)根搜索法2. 垃圾回收算法1)复制算法2)标记-清除算法3)标记-整理算法4)分代收集算法3. java垃圾收集器新生代GC器:1)Serial垃圾收集器2)ParNew垃圾收集器3)Parallel Scavenge垃圾收集器老年代GC器1)Serial和Parallel Scavenge都有对应的老年代版本2)CMS垃圾收集器4.java对象的内存分配位置5.java TLAB 1. 垃圾收集算法 1)引

GC垃圾回收 | 深入理解G1垃圾收集器和GC日志

来源:并发编程网链接:http://ifeve.com/深入理解G1垃圾收集器/ G1 GC是Jdk7的新特性之一.Jdk7+版本都可以自主配置G1作为JVM GC选项:作为JVM GC算法的一次重大升级.DK7u后G1已相对稳定.且未来计划替代CMS.所以有必要深入了解下: 不同于其他的分代回收算法.G1将堆空间划分成了互相独立的区块.每块区域既有可能属于O区.也有可能是Y区,且每类区域空间可以是不连续的(对比CMS的O区和Y区都必须是连续的).这种将O区划分成多块的理念源于:当并发后台线程寻

二、Java如何分配和回收内存?Java垃圾收集器如何工作?

线程私有的内存区域随用户线程的结束而回收,内存分配编译期已确定,内存分配和回收具有确定性.共享线程随虚拟机的启动.结束而建立和销毁,在运行期进行动态分配.垃圾收集器主要对共享内存区域(堆和方法区)进行垃圾收集回收. Java如何实现内存动态分配和内存垃圾的回收? 1.哪些内存需要回收(垃圾收集器内存回收的对象)?已经"死亡"的对象,那如何判定对象已经"死亡"了? Java堆回收的内存:已经"死亡"的对象 方法区回收的内存:废弃的常量和无用的类 2