1、对象已死?

a、引用计数算法:缺点是它很难解决对象之间的相互循环引用的问题,Java语言中没有选用它。

b、根搜索算法(GC Roots Tracing):通过一系列的名为“GC Roots”的对象作为起始点,开始向下搜索,走过的路径称为引用链,当一个对象没有任何引用链相连,表面此对象不可达。在Java语言中,可作为GC Roots的对象包括:

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

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

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

  本地方法栈中JNI的引用的对象。

c、再谈引用:Java把引用分成强引用,软引用,弱引用和虚引用。由强到弱。

  强引用:只要强应用在存在,垃圾收集器永远不会回收掉被引用的对象。

  软引用:在系统将要发生内存溢出异常之前,把对象列进回收范围之中并进行第二次回收。如果这次回收之后还是没有足够的内存,才会抛出内存溢出异常。SoftReference

  弱引用:被弱引用关联的对象只能生存到下一次垃圾回收发生之前。WeakReference

  虚引用:一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。唯一目的是:对象被回收时收到一个系统通知。PhantomReference

d、生存还是死亡?

  对象不可达之后,进入“缓刑”阶段。第一次根搜索后,不可达对象有两种情况:一是直接回收,二是放入F-Queue队列。放入F-Queue队列的条件是覆盖了finalize()方法且没有被调用过。总结一下就是:对象可以通过覆盖finalize()方法在被GC时拯救自己一次。注意:任何一个对象的finalize()方法都只会被系统自动调用一次。

e、回收方法区

  方法区的回收主要集中在:废弃常量和无用的类。废弃常量的回收与Java堆对象的回收类似,无用类的回收需要满足3个条件:而且只是可以回收,通过参数控制。

  该类的所有实例都已经被回收

  加载该类的ClassLoader已经被回收

  该类对应的Class对象没有在任何地方被引用。

  在大量使用反射、动态代理、CGLib等bytecode框架的场景,以及动态生成JSP和OSGi这类频繁自定义ClassLoader的场景都需要虚拟机具备类卸载的功能。

2、垃圾收集算法

  a、标记-清除算法:分成标记和清除两个阶段。首先标记出所有需要回收的对象,标记完成后统一回收掉所有被标记的对象。

  有点:实现简单,逻辑直接

  缺点两个:效率比较低,空间不连续,大量碎片。

  b、复制算法:为了解决效率问题。平分内存成两块,每次只用一块,快用完时,复制替换。

  优点:实现简单,运行高效

  缺点两个:可用内存是原来的一半;当对象存活率较高时,复制带来低效率。

  HotSpot虚拟机吻合了IBM的研究,改进了该算法,分成了一个较大的Eden区和两个较小的Survivor区。效率更好,但需要担保内存。比较符合新生代使用。

  c、标记-整理算法:不直接清理可回收对象,让所有存活的对象向一端移动,然后清理掉边界以外的内存。比较适合于老年代使用。

  d、分代收集算法:根据对象的存活周期不同将内存划分为几块。根据各个年代的特点采用最合适的收集算法。新生代一般使用复制算法,老年代采用标记-清除算法或者标记-整理算法。

3、垃圾收集器

  

  上图展示了7种作用于不同分代的收集器,连线表示收集器之间可以搭配使用。

  a、Serial收集器:

  它是一个单线程的收集器,只会使用一个CPU和一条收集线程去完成垃圾收集工作。同时,它也是串行收集器:在进行垃圾收集时,必须暂停其他所有的工作线程(Stop The World),直到它收集结束。在用户不可见的情况下,把用户的正常工作线程全部停掉。

  这个简单而高效(特别是单个CPU的环境)的收集器适合于运行在Client模式下的虚拟机。

  b、ParNew收集器

  是Serial收集器的多线程版本,与Serial收集器唯一的区别就在于使用了多条线程进行收集。

  目前只有Serial和ParNew能与CMS收集器配合工作。CMS是JDK1.5中引入的第一款并发收集器:垃圾收集线程与用户线程可同时工作。ParNew在多CPU的情况下才具备性能优势。

  c、Parallel Scavenge收集器

  是一个新生代收集器,使用复制算法,并行多线程收集器。它的特点是关注于达到一个可控制的吞吐量,最大地利用CUP的时间。同时,Parallel Scavenge收集器通过一个开关参数还可以开启自适应调节策略。

  d、Serial Old收集器

  它是Serial收集器的老年代版本,单线程,标记-整理算法。主要用于Client模式下。同时:可以Parallel Scavenge收集器搭配使用,作为CMS收集器的后背预案。

  e、Parallel Old收集器

  它是Parallel Scavenge收集器的老年代版本,多线程和标记-整理算法。与Paralle Scavenge一起打造吞吐量优先的组合。在注重吞吐量及CPU资源敏感的场合,考虑使用。

  f、CMS收集器(Concurrent Mark Sweep)

  以获取最短回收停顿时间为目标,适合于注重服务的相应速度的场合。基于标记-清除算法。整个过程四个步骤:

  初始标记(CMS initial mark)

  并发标记(CMS concurrent mark)

  重新标记(CMS remark)

  并发清除(CMS concurrent sweep)

  注意:初始标记和重新标记一样有Stop The World。初始标记只是标记一下GC Roots能直接关联到的对象,速度很快,并发标记阶段就是进行Roots Tracing的过程,而重新标记则是为了修正并发标记期间,因用户程序运作而导致标记发生变动的那一部分对象的标记记录,停顿时间不长。耗时较长的并发标记和并发清除过程,收集线程和用户线程可一起工作。

  缺点:

  对CPU资源非常敏感。默认启动线程数:(CPU数量+3)/4。

  无法处理浮动垃圾,可能出现Concurrent Mode Failure失败导致一次Full GC。CMS运行期间预留的内存无法满足程序的需要,出现Concurrent Mode Failure失败。虚拟机启动后备预案,临时使用Serial Old收集器重新老年代的垃圾收集。

  使用的标记-清除算法导致大量内存碎片。可能导致提前Full GC。使用参数可控制Full GC发生后附带的空间碎片整理频率。

  g、G1收集器

  与CMS相比有两个改进:基于标记-整理算法,消除了内存碎片问题;精确地控制停顿时长。G1将整个Java堆分成多个大小固定的独立区域,跟踪区域垃圾堆积程度,在后台维护一个优先列表,每次根据允许的收集时间,优先收集垃圾最多的区域。

  4、垃圾收集器参数总结

深入理解Java虚拟机之读书笔记二 垃圾收集器的更多相关文章

  1. 《深入理解 Java 虚拟机》读书笔记:垃圾收集器与内存分配策略

    正文 垃圾收集器关注的是 Java 堆和方法区,因为这部分内存的分配和回收是动态的.只有在程序处于运行期间时才能知道会创建哪些对象,也才能知道需要多少内存. 虚拟机栈和本地方法栈则不需要过多考虑回收的 ...

  2. 《深入理解Java虚拟机》读书笔记:垃圾收集器与内存分配策略

    请移步至:http://zhanjindong.info/2014/05/18/java-gc/

  3. 《深入java虚拟机》读书笔记之垃圾收集器与内存分配策略

    前言 该读书笔记用于记录在学习<深入理解Java虚拟机--JVM高级特性与最佳实践>一书中的一些重要知识点,对其中的部分内容进行归纳,或者是对其中不明白的地方做一些注释.主要是方便之后进行 ...

  4. 《深入理解java虚拟机》读书笔记二——第三章

    第三章 垃圾收集器与内存分配策略 1.判断对象是否已死 引用计数法: 给对象添加一个引用计数器,每当有一个地方引用它时,计数器值就加1,每当引用失效时,计数器值就减1. 任何时刻计数器为0的对象就是不 ...

  5. 《深入理解Java虚拟机》读书笔记二

    第三章 垃圾收集器与内存分配策略 1.判断对象是否已死 引用计数法: 给对象添加一个引用计数器,每当有一个地方引用它时,计数器值就加1,每当引用失效时,计数器值就减1. 任何时刻计数器为0的对象就是不 ...

  6. 《深入理解java虚拟机》学习笔记四/垃圾收集器GC学习/一

    Grabage Collection      GC GC要完毕的三件事情: 哪些内存须要回收? 什么时候回收? 怎样回收? 内存运行时区域的各个部分中: 程序计数器.虚拟机栈.本地方法栈这3个区域随 ...

  7. 《深入理解 Java 虚拟机》读书笔记:Java 内存区域与内存溢出异常

    前言 最近开始看这本书,记得前段时间拿起这本书的时候,心情是相当沉重的!当时的剧本是这样的-- 内景.家里 - 下午 我(画外):唉,有点无聊啊!(偶然撇过书架)这么多书得看到什么时候啊,要不要拿一本 ...

  8. 《深入理解java虚拟机》读书笔记-第二章Java内存区域和内存溢出异常

    java1.7和java8的jvm存在差异,本文先按照<深入理解java虚拟机>的讲解内容总结,并将java8的改变作为附录放在文末 一丶运行时数据区域 ​ 图:java虚拟机运行时数据区 ...

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

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

随机推荐

  1. segmentfault.com mongo出识以及对数组的操作

    https://segmentfault.com/a/1190000003951602 首先推荐个工具,no-sql-manager-for-mongodb-professional,虽然收费,但是每 ...

  2. zabbix 3.0快速安装简介(centos 6)

    zabbix快速安装 系统版本:centos 6 1.yum源配置和zabbix.msyql安装 rpm -ivh http://mirrors.aliyun.com/zabbix/zabbix/3. ...

  3. 批处理学习:for语句详解【经典】

    大纲 一 前言 二 for语句的基本用法 三 for /f (delims.tokens.skip.eol.userbackq.变量延迟) 四 for /r (递归遍历) 五 for /d (遍历目录 ...

  4. JavaWeb学习笔记——开发动态WEB资源(八)cookies和httpsession

    会话: cookies: (1)cookies是WEB服务器发送到浏览器的简短文本信息 (2)cookies可以禁用 httpsession: 一次会话是从你打开浏览器开始到你关闭浏览器结束 提供一种 ...

  5. Unity3D SceneView Camera

    http://forum.unity3d.com/threads/moving-scene-view-camera-from-editor-script.64920/

  6. Swift控制器加载xib Swift Controller'view load from xib

    override func loadView() { NSBundle.mainBundle().loadNibNamed("ViewController", owner: sel ...

  7. LaTeX 页眉页脚的设置

    Latex中页眉页脚的设置 1. 首先要加页眉页脚的话,需要启动宏: 我通常用fancyhdr宏包来设置页眉和页脚. \usepackage{fancyhdr} 我们在 LaTeX 中先把 page ...

  8. css媒体查询

    简单解释:http://zh.learnlayout.com/media-queries.html 深入学习1:https://developer.mozilla.org/en-US/docs/Web ...

  9. php Hash Table(二) Hash函数

    哈希表最关键的几个方面有: 通过key访问(通过哈希函数计算出key) 映射到数据结构中(哈希表本身的存储结构) 映射的处理(冲突或者碰撞检测和处理函数) 理解PHP的哈希算法 一般来说对于整形索引进 ...

  10. NoSQL 简介及什么是AICD

    NoSQL 简介 NoSQL(NoSQL = Not Only SQL ),意即"不仅仅是SQL". 在现代的计算系统上每天网络上都会产生庞大的数据量. 这些数据有很大一部分是由关 ...