参考文档:https://www.toutiao.com/a6691966641242112516/

垃圾搜集算法

标记-清除法

标记-清除算法采用从根集合(GC Roots)进行扫描,对存活的对象进行标记,标记完毕后,再扫描整个空间中未被标记的对象,进行回收,如下图所示。

标记-清除算法不需要进行对象的移动,只需对不存活的对象进行处理,在存活对象比较多的情况下极为高效。但由于标记-清除算法直接回收不存活的对象,因此会造成内存碎片。

复制算法

复制算法的提出是为了克服句柄的开销和解决内存碎片的问题。

它开始时把堆分成 一个对象面和多个空闲面, 程序从对象面为对象分配空间,当对象满了,基于copying算法的垃圾收集就从根集合(GC Roots)中扫描活动对象,并将每个活动对象复制到空闲面(使得活动对象所占的内存之间没有空闲洞)。这样空闲面变成了对象面,原来的对象面变成了空闲面,程序会在新的对象面中分配内存。

标记-整理算法

标记-整理算法采用标记-清除算法一样的方式进行对象的标记,但在清除时不同,在回收不存活的对象占用的空间后,会将所有的存活对象往左端空闲空间移动,并更新对应的指针。

标记-整理算法是在标记-清除算法的基础上,又进行了对象的移动,因此成本更高,但是却解决了内存碎片的问题。

具体流程见下图:

分代收集算法

分代收集算法是目前大部分JVM的垃圾收集器采用的算法。它的核心思想是根据对象存活的生命周期将内存划分为若干个不同的区域。

一般情况下将堆区划分为老年代(Tenured Generation)和新生代(Young Generation),在堆区之外还有一个代就是永久代(Permanet Generation)。

老年代的特点是每次垃圾收集时只有少量对象需要被回收,而新生代的特点是每次垃圾回收时都有大量的对象需要被回收,那么就可以根据不同代的特点采取最适合的收集算法。

年轻代回收算法

a) 所有新生成的对象首先都是放在年轻代的。年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象。

b) 新生代内存按照8:1:1的比例分为一个eden区和两个survivor(survivor0,survivor1)区。

大部分对象在Eden区中生成,回收时先将eden区存活对象复制到一个survivor0区,然后清空eden区。

当这个survivor0区也存放满了时,则将eden区和survivor0区存活对象复制到另一个survivor1区,然后清空eden和这个survivor0区,此时survivor0区是空的

然后将survivor0区和survivor1区交换,即保持survivor1区为空, 如此往复。

c) 当survivor1区不足以存放 eden和survivor0的存活对象时,就将存活对象直接存放到老年代。

若是老年代也满了就会触发一次Full GC,也就是新生代、老年代都进行回收。

d) 新生代发生的GC也叫做Minor GC,MinorGC发生频率比较高(不一定等Eden区满了才触发)。

年老代回收算法

a) 在年轻代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代中。

因此,可以认为年老代中存放的都是一些生命周期较长的对象。

b) 内存比新生代也大很多(大概比例是1:2),当老年代内存满时触发Major GC即Full GC,Full GC发生频率比较低,老年代对象存活时间比较长,存活率标记高。

持久代回收算法

用于存放静态文件,如Java类、方法等。持久代对垃圾回收没有显著影响,但是有些应用可能动态生成或者调用一些class,例如Hibernate 等,

在这种时候需要设置一个比较大的持久代空间来存放这些运行过程中新增的类。

持久代也称方法区。

GC什么时候被触发

一般情况下,当新对象生成,并且在Eden申请空间失败时,就会触发Scavenge GC,对Eden区域进行GC,清除非存活对象,并且把尚且存活的对象移动到Survivor区。然后整理Survivor的两个区。

这种方式的GC是对年轻代的Eden区进行,不会影响到年老代。因为大部分对象都是从Eden区开始的,同时Eden区不会分配的很大,所以Eden区的GC会频繁进行。

因而,一般在这里需要使用速度快、效率高的算法,使Eden去能尽快空闲出来。

Scavenge GC

一般情况下,当新对象生成,并且在Eden申请空间失败时,就会触发Scavenge GC,对Eden区域进行GC,清除非存活对象,并且把尚且存活的对象移动到Survivor区。然后整理Survivor的两个区。

这种方式的GC是对年轻代的Eden区进行,不会影响到年老代。因为大部分对象都是从Eden区开始的,同时Eden区不会分配的很大,所以Eden区的GC会频繁进行。

因而,一般在这里需要使用速度快、效率高的算法,使Eden去能尽快空闲出来。

Full GC

对整个堆进行整理,包括Young、Tenured和Perm。

Full GC因为需要对整个堆进行回收,所以比Scavenge GC要慢,因此应该尽可能减少Full GC的次数。

在对JVM调优的过程中,很大一部分工作就是对于Full GC的调节。

有如下原因可能导致Full GC:

  • 老年代(Tenured)被写满;
  • 持久代(Perm)被写满;
  • System.gc()被显示调用;
  • 上一次GC之后Heap的各域分配策略动态变化;

JVM垃圾回收算法图解的更多相关文章

  1. JVM垃圾回收算法解析

    JVM垃圾回收算法解析 标记-清除算法 该算法为最基础的算法.它分为标记和清除两个阶段,首先标记出需要回收的对象,在标记结束后,统一回收.该算法存在两个问题:一是效率问题,标记和清除过程效率都不太高, ...

  2. JVM垃圾回收算法(最全)

    JVM垃圾回收算法(最全) 下面是JVM虚拟机运行时的内存模型: 1.方法区 Perm(永久代.非堆) 2.虚拟机栈 3.本地方法栈 (Native方法) 4.堆 5.程序计数器 1 首先的问题是:j ...

  3. JVM垃圾回收算法及回收器详解

    引言 本文主要讲述JVM中几种常见的垃圾回收算法和相关的垃圾回收器,以及常见的和GC相关的性能调优参数. GC Roots 我们先来了解一下在Java中是如何判断一个对象的生死的,有些语言比如Pyth ...

  4. JVM 垃圾回收算法和垃圾回收器

    JVM 垃圾回收算法和垃圾回收器. 一.垃圾回收的区域 栈:栈中的生命周期是跟随线程,所以一般不需要关注. 堆:堆中的对象是垃圾回收的重点. 方法区:这一块也会发生垃圾回收,不过这块的效率比较低,一般 ...

  5. 记录JVM垃圾回收算法

    垃圾回收算法可以分为三类,都基于标记-清除(复制)算法: Serial算法(单线程) 并行算法 并发算法 JVM会根据机器的硬件配置对每个内存代选择适合的回收算法,比如,如果机器多于1个核,会对年轻代 ...

  6. JVM 垃圾回收算法

    在说垃圾回收算法之前,先谈谈JVM怎样确定哪些对象是“垃圾”. 1.引用计数器算法: 引用计数器算法是给每个对象设置一个计数器,当有地方引用这个对象的时候,计数器+1,当引用失效的时候,计数器-1,当 ...

  7. Java基础:JVM垃圾回收算法

    众所周知,Java的垃圾回收是不需要程序员去手动操控的,而是由JVM去完成.本文介绍JVM进行垃圾回收的各种算法. 1. 如何确定某个对象是垃圾 1.1. 引用计数法 1.2. 可达性分析 2. 典型 ...

  8. JVM 垃圾回收算法及案例分析

    一. 在说垃圾回收算法之前,先谈谈JVM怎样确定哪些对象是“垃圾”. 1.引用计数器算法: 引用计数器算法是给每个对象设置一个计数器,当有地方引用这个对象的时候,计数器+1,当引用失效的时候,计数器- ...

  9. 第四章 JVM垃圾回收算法

    说明:在阅读本篇之前,需要知道怎么判断对象的存活与否,见<第三章 JVM内存回收区域+对象存活的判断+引用类型+垃圾回收线程> 注意:本文主要参考自<分布式Java应用:基础与实践& ...

随机推荐

  1. Spring——框架

    [定义] 框架就是制定一套规则或规范(思想),大家(程序员)在该规范或者规则(思想)下工作. 或者说是使用别人搭好的舞台,你来表演. [特点] ——半成品 ——封装了特定的处理流程和控制逻辑 ——成熟 ...

  2. Kohana重写接收不到get参数问题

    .htaccess,不需要重启apache # Turn on URL rewriting RewriteEngine On # Installation directory RewriteBase ...

  3. Codeforces Round #603 (Div. 2)F. Economic Difficulties

    F. Economic Difficulties 题目链接: https://codeforces.com/contest/1263/problem/F 题目大意: 两棵树,都有n个叶子节点,一棵树正 ...

  4. 前端String类型转JSON类型

    在js中通过ajax获取数据后,赋值给前端树形插件zTree中的zNodes,但一直失败如图: 浏览器端报错: 于是我将zNodes变量的值直接写死,并打印这两个的值,如图 再次运行成功.浏览器控制台 ...

  5. uploadify上传插件参数的一些设置

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. js 在输出到页面的5中方式

    1.alert("要输出的内容"); ->在浏览器中弹出一个对话框,然后把要输出的内容展示出来 ->alert都是把要输出的内容首先转换为字符串然后在输出的 2.doc ...

  7. Cocoapods 版本

    查看当前安装的版本 gem list 卸载版本 gem uninstall cocoapods 安装 gem install cocoapods gem install cocoapods -v 1. ...

  8. 启用和配置 FILESTREAM

    2017/08/23 在开始使用 FILESTREAM 之前,必须在 SQL Server 数据库引擎实例中启用 FILESTREAM. 本主题说明了如何使用 SQL Server 配置管理器来启用 ...

  9. Window7 系统下重新建立一个新分区

    为了方便使用,准备在原来分区上再分割出一个分区,步骤如下 首先右击计算机,选择管理打开计算机管理窗口,选择磁盘管理,当前窗口右侧会出现当前计算机所有已存在的分区列表. 选择要进行分区的磁盘,右击选择压 ...

  10. mysql5.6.36 源码安装过程

    参考:http://www.linuxidc.com/Linux/2015-06/119354.htm cmake编译时,提示错误 CMake Error: The source directory ...