Java垃圾收集(Garbage Collection,GC)

某一个时点,一个对象如果有一个以上的引用(Rreference)指向它,那么该对象就为活着的(Live),

否则死亡(Dead),视为垃圾,可被垃圾回收器回收再利用。

垃圾回收操作需要消耗CPU、线程、时间等资源,所以容易理解的是垃圾回收操作不是实时的发生(对象死亡后不会马上释放),

当内存消耗完或者是达到某一个指标(Threshold,使用内存占总内存的比列)时,触发垃圾回收操作。

GC需要完成的三件事情:

     哪些内存需要回收?

            --如何判断对象已死?用 根搜索算法

            这个算法的基本思路就是通过一系列的名为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain)。

            当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。

            在Java语言里,可作为GC Roots的对象包括下面几种:

                虚拟机栈(栈帧中的本地变量表)中的引用的对象

                方法区中的类静态属性引用的对象。

                方法区中的常量引用的对象。

                本地方法栈中JNI(即一般说的Native方法)的引用的对象

    什么时候回收?

            当内存消耗完或者是达到某一个阀值(Threshold,使用内存占总内存的比列)时,触发垃圾回收操作。阀值可通过JVM参数配置。

    如何回收?

    GC机制的基本算法是 分代收集,

    当新生代的Eden区满的时候,执行Minor GC,也叫 Young GC。使用了复制算法。

    当老年代内存不足时,将执行Major GC,也叫 Full GC。使用了标记-清除算法 或 标记-整理算法。

在GC机制中,起重要作用的是垃圾收集器,垃圾收集器是GC的具体实现。如下图,

  

新生代收集器:(都是使用 停止复制算法

  • Serial收集器:使用停止复制算法,使用一个线程进行GC,串行,其它工作线程暂停。使用-XX:+UseSerialGC可以使用Serial+Serial Old模式运行进行内存回收(这也是虚拟机在Client模式下运行的默认值)
  • ParNew收集器:使用停止复制算法,Serial收集器的多线程版,用多个线程进行GC,并行,其它工作线程暂停,关注缩短垃圾收集时间。使用-XX:+UseParNewGC开关来控制使用ParNew+Serial Old收集器组合收集内存;使用-XX:ParallelGCThreads来设置执行内存回收的线程数。
  • Parallel Scavenge 收集器:使用停止复制算法,关注CPU吞吐量。即运行用户代码的时间/总时间,比如:JVM运行100分钟,其中运行用户代码99分钟,垃 圾收集1分钟,则吞吐量是99%,这种收集器能最高效率的利用CPU适合运行后台运算(关注缩短垃圾收集时间的收集器,如CMS,等待时间很少,所以适 合用户交互,提高用户体验)。使用-XX:+UseParallelGC开关控制使用Parallel Scavenge+Serial Old收集器组合回收垃圾(这也是在Server模式下的默认值);使用-XX:GCTimeRatio来设置用户执行时间占总时间的比例,默认99,即1%的时间用来进行垃圾回收。使用-XX:MaxGCPauseMillis设置GC的最大停顿时间(这个参数只对Parallel Scavenge有效),用开关参数-XX:+UseAdaptiveSizePolicy可以进行动态控制,如自动调整Eden/Survivor比例,老年代对象年龄,新生代大小等,这个参数在ParNew下没有。

老年代收集器:

    • Serial Old收集器:单线程收集器,串行,使用标记整理(整理的方法是Sweep(清理)和Compact(压缩),清理是将废弃的对象干掉,只留幸存的对象,压缩是将移动对象,将空间填满保证内存分为2块,一块全是对象,一块空闲)算法,使用单线程进行GC,其它工作线程暂停(注意,在老年代中进行标记整理算法清理,也需要暂停其它线程),在JDK1.5之前,Serial Old收集器与ParallelScavenge搭配使用。
    • Parallel Old收集器:老年代收集器,多线程,并行,多线程机制与Parallel Scavenge差不错,使用标记整理(与Serial Old不同,这里的整理是Summary(汇总)和Compact(压缩),汇总的意思就是将幸存的对象复制到预先准备好的区域,而不是像Sweep(清理)那样清理废弃的对象)算法,在Parallel Old执行时,仍然需要暂停其它线程。Parallel Old在多核计算中很有用。Parallel Old出现后(JDK 1.6),与Parallel Scavenge配合有很好的效果,充分体现Parallel Scavenge收集器吞吐量优先的效果。使用-XX:+UseParallelOldGC开关控制使用Parallel Scavenge +Parallel Old组合收集器进行收集。
    • CMS(Concurrent Mark Sweep)收集器:老年代收集器,致力于获取最短回收停顿时间(即缩短垃圾回收的时间),使用标记清除算法,多线程,优点是并发收集用户线程可以和GC线程同时工作),停顿小。使用-XX:+UseConcMarkSweepGC进行ParNew+CMS+Serial Old进行内存回收,优先使用ParNew+CMS(原因见后面),当用户线程内存不足时,采用备用方案Serial Old收集。

G1收集器:在JDK1.7中正式发布,与现状的新生代、老年代概念有很大不同,目前使用较少,不做介绍。

深入理解java:1.3. 垃圾收集的更多相关文章

  1. 深入理解java虚拟机之垃圾收集器

    Java一个重要的优势就是通过垃圾管理器GC (Garbage Collection)自动管理和回收内存,程序员无需通过调用方法来释放内存.也因此很好多的程序员可能会认为Java程序不会出现内存泄漏的 ...

  2. 深入理解Java虚拟机:垃圾收集器与内存分配策略

    目录 3.2 对象已死吗 判断一个对象是否可被回收 引用类型 finalize() 回收方法区 3.3. 垃圾收集算法 1.Mark-Sweep(标记-清除)算法 2.Copying(复制)算法 3. ...

  3. 《深入理解Java虚拟机》垃圾收集器

    说起垃圾收集(Garbage Collection,GC),大部分人都把这项技术当做Java语言的伴生产物.事实上,GC的历史远比Java久远,1960年诞生于MIT的Lisp是第一门真正使用内存动态 ...

  4. 《深入理解Java虚拟机》——垃圾收集器与内存分配策略

    GC需要完成: 哪些内存需要回收 什么时候回收 如何回收 如何确定对象不再使用 引用计数算法 给对象添加一个引用计数器,当有一个地方引用它时,计数器值进行加1操作:当引用失效时,计数器值进行减1操作: ...

  5. 深入理解Java虚拟机笔记——垃圾收集器与内存分配策略

    目录 判断对象是否死亡 引用计数器算法 可达性分析算法 各种引用 回收方法区 垃圾收集算法 标记-清除算法 复制算法 标记-整理算法 分代收集算法 HotSpot算法实现 枚举根节点 GC停顿(Sto ...

  6. 深入理解java虚拟机(3)垃圾收集器与内存分配策略

    一.根搜索算法: (1)定义:通过一系列名为"GC Roots"的对象作为起点,从这些起点开始向下搜索,搜索走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连的时 ...

  7. 深入理解java虚拟机----->垃圾收集器与内存分配策略(下)

    1.  前言 内存分配与回收策略 JVM堆的结构分析(新生代.老年代.永久代) 对象优先在Eden分配 大对象直接进入老年代 长期存活的对象将进入老年代 动态对象年龄判定 空间分配担保  2.  垃圾 ...

  8. 《深入理解Java虚拟机》(三)垃圾收集器与内存分配策略

    垃圾收集器与内存分配策略 详解 3.1 概述 本文参考的是周志明的 <深入理解Java虚拟机>第三章 ,为了整理思路,简单记录一下,方便后期查阅. 3.2 对象已死吗 在垃圾收集器进行回收 ...

  9. 《深入理解Java虚拟机》(六)堆内存使用分析,垃圾收集器 GC 日志解读

    堆内存使用分析,GC 日志解读 重要的东东 在Java中,对象实例都是在堆上创建.一些类信息,常量,静态变量等存储在方法区.堆和方法区都是线程共享的. GC机制是由JVM提供,用来清理需要清除的对象, ...

  10. 《深入理解java虚拟机》第三章 垃圾收集器与内存分配策略

    第三章 垃圾收集器与内存分配策略 3.1 概述 哪些内存需要回收 何时回收 如何回收 程序计数器.虚拟机栈.本地方法栈3个区域随线程而生灭. java堆和方法区的内存需要回收.   3.2 对象已死吗 ...

随机推荐

  1. 如何将vim打造成Linux下的source insight

    编写者:龙诗科 邮箱:longshike2010@163.com 2016-01-06 众所周知,windows下的source insight是阅读项目代码的神器,其神奇之处在于可以根据当前鼠标所指 ...

  2. Spring 整合过滤器

    过滤器Filter是Servlet的一个技术,可通过过滤器对请求进行拦截,比如读取session判断用户是否登录.判断访问的请求URL是否有权限. 1.使用@WebFilter注解 controlle ...

  3. LOJ-6278-数列分块入门2(分块)

    链接: https://loj.ac/problem/6278 题意: 给出一个长为 的数列,以及 个操作,操作涉及区间加法,询问区间内小于某个值 的元素个数. 思路: 分块,用vector维护每个区 ...

  4. js 复杂研究

    function test_001() { var t =0; return t || out_str("t未定义"), //1 // 执行1句;在执行2句; t||null // ...

  5. keras学习笔记-bili莫烦

    一.keras的backend设置 有两种方式: 1.修改JSON配置文件 修改~/.keras/keras.json文件内容为: { "iamge_dim_ordering":& ...

  6. vs中free内存失败

    关于vs中free内存失败: 主要有以下两个原因: 1. 函数参数调用写错.特别是传指针进去的时候,若形参与实参不对应,会出错. 2. 内存分配不够,这个原因主要是因为程序中访问到了内存外的地址,即使 ...

  7. 基于 Golang 完整获取百度地图POI数据的方案

    百度地图为web开发者提供了基于HTTP/HTTPS协议的丰富接口,其中包括地点检索服务,web开发者通过此接口可以检索区域内的POI数据.百度地图处于数据保护对接口做了限制,每次访问服务,最多只能检 ...

  8. linux crontab -e生成日期格式

    近期公司数据库服务器要上双活项目,实施顾问要收集服务器(磁盘性能数据)IO及VM的一些相关信息,并已日期时间格式生成文件 用crontab –e增加以下内容,它的作用是每隔1个小时启动一次iostat ...

  9. sqli-labs(10)

    基于双引号的时间盲注 先来随便测试一下 发现 错不错都是返回的真确的结果 那么应该是被从定向了 我们可以输入 and sleep(5) %23 测试 加’发现立刻返回 加双引号发现报错了 过了5秒才返 ...

  10. 【Python】学习笔记九:面向对象拓展

    调用类的其他信息 在定义方法的时候,必须有self这一参数.这个参数表示某个对象,对象拥有类的所有性质.那么我们可以通过self,调用类属性 class people(object): action ...