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. 网络存储(三)之ISCSI搭建的入门

    搭建iscsi 我们就拿两台linux服务器来做吧, 服务器系统均为CentOs6.6 64位的,信息如下 IP 安装的软件 192.168.22.142 iscsi target端:scsi-tar ...

  2. OpenCV图像金字塔:高斯金字塔、拉普拉斯金字塔与图片尺寸缩放

    这篇已经写得很好,真心给作者点个赞.题目都是直接转过来的,直接去看吧. Reference Link : http://blog.csdn.net/poem_qianmo/article/detail ...

  3. javascript的propertyIsEnumerable()方法使用介绍

    hasOwnProperty() 方法用来判断某个对象是否含有指定的自身属性. propertyIsEnumerable()是用来检测属性是否属于某个对象的,如果检测到了,返回true,否则返回fal ...

  4. Redis总结(二)C#中如何使用redis

    上一篇讲述了安装redis<Redis总结(一)Redis安装>,同时也大致介绍了redis的优势和应用场景.本篇着重讲解.NET中如何使用redis和C#. Redis官网提供了很多开源 ...

  5. Think in Java(Java编程思想)-第2章 一切都是对象

    1. String s = "asdf"//创建一个String引用,并初始化. String s = new String("asdf")//创建一个新对象, ...

  6. 在yii2验证之前执行一些额外自定义验证

    <?php $form = ActiveForm::begin([ 'id' => $model->formName(), 'action' => ['/apitools/de ...

  7. java正则表达式 --简单认识

    学习目标 正则表达式的作用正则表达式的模式匹配Pattern类和Matcher类的使用掌握String对正则的支持具体内容一.认识正则(为什么要有正则) 方便的对数据进行匹配 执行复杂的字符串验证.拆 ...

  8. MongoDB创建数据库和集合命令db.createCollection详解(转)

    切换/创建数据库 use yourDB;  当创建一个集合(table)的时候会自动创建当前数据库 完整的命令如下:db.createCollection(name, {capped: <Boo ...

  9. html、css杂记

    1:浮动 <div style="float: left"> 2:清除浮动,把父div撑起来 <div style="clear:both"& ...

  10. 360chrome,google chrome浏览器使用jquery.ajax加载本地html文件

    使用360chrome和google chrome浏览器加载本地html文件时,会报错,提示: XMLHttpRequest cannot load file:///Y:/jswg/code/html ...