1. 垃圾收集算法

 
    JVM的垃圾收集算法在不同的JVM实现中有所不同,且在平时工作中一般不会深入到收集算法,因此只对算法做较为简单的介绍。
 
    1.1 标记-清除算法
 
        这种算法是非常直观的,也是最为基础的收集算法(Mark-Sweep)算法,这种算法将回收分为两个阶段:首先标记所有需要回收的对象,然后在完成标记后统一回收掉被标记的对象。这种算法是如此的基础,以至于后面的算法都是基于该思路,并对其确定进行改进所得的。
 
        这种算法的缺点主要有两个:
 
        1. 效率较低,整个回收过程分为标记-回收两个阶段
 
        2. 内存碎片,标记清除之后存在较多内存碎片,可能导致需要连续的较大的内存空间时,没有满足需要的内存空间,从而不得不导致另外一次GC。
 
       
 
    1.2 复制算法
 
        为了解决效率问题,复制算法出现了,其将内存划分为容量相等的两块,每次只使用其中一块。当一块的内存用完了,就将活着的对象复制到另外的内存块上,然后把使用过的空间一次清理掉。这样只对一块内存空间进行回收,相当的高效。
 
        但这种算法的问题是将实际可用内存的大小缩小了一般,在内存价格还相当昂贵的今天,代价有些太高了。
 
       
 
    现在的商业虚拟机都使用此种算法来回收新生代,根据IBM研究表明,新生代中98%的对象是朝生夕死的,所以并不需要按照1:1来划分内存空间,而是将新生代划分为一块较大的Eden和两块较小的Survivor空间,每次使用Eden和其中一块Survivor。
    回收时,将Eden和Survivor中存活的对象一次性复制到另外的Survivor空间,并清理掉Eden和Survivor空间。这样,可以减少浪费至10%,当survivor空间不够时,需要老年代进行分配担保(Handle Promotion,如果另一个Survivor没有足够空间,则存放到老年代)。
 
    1.3 标记 - 整理算法
 
        复制算法在存货对象较多时需要执行大量的复制操作,这对老年代来说是不合适的,因此有人就提出了标记-整理算法,过程与标记-清除算法一样,但后续步骤不是对可回收对象进行清理,而是让所有的对象都向一端移动,然后直接清理掉边界之外的内存。
 
       
 
        1.4 分代收集算法
 
            当前的商业虚拟机均使用分代收集算法,将对象按照存活周期分为几块,一般将Java堆分为新生代与老年代,从而可以根据不同年代的特点使用不同的收集算法。
 
            如新生代中存在大量死去的对象,只有少量存活,使用复制算法;老年代中因存活对象数量多,且没有额外空间,因此需要采用标记 - 清除或 标记 - 清理算法。
 
2. 垃圾收集器
 
    垃圾收集器是垃圾收集算法的具体实现,Java虚拟机对垃圾收集器如何实现并未做规定,因此不同厂商会有各自的垃圾收集器。如HotSpot虚拟机中的收集器如下所示,其中存在连线的收集器即可搭配使用。
 
    但现在没有最好的收集器,都需要根据具体环境来选择。
 
   
 
    2.1 Serial收集器
 
        串行收集器是最为基本的收集器,它是单线程的,而且在运行时,会停掉其他所有的工作线程(Stop the world),直到其收集结束。在实际应用中,用户很难忍受程序运行暂停。
 
        人们在努力的减少收集器的停顿时间,但没有办法完全消除,虽然Serial收集器有着种种缺点,但其简单而高效,对于Client型应用,其仍是新生代默认的收集器(桌面应用,内存小且停顿时间可忍受)。
 
    2.2 ParNew收集器
 
        ParNew收集器是Serial收集器的多线程版本,且加入了多个控制参数,并与Serial公用相当多的代码
 
        ParNew除了多线程之外,与其他Serial收集器相比并没有太多创新,但其却是许多运行在Server模式下虚拟机首选的新生代收集器,主要是由于它可以通CMS收集器相配合使用。
 
        在单CPU环境下,ParNew性能甚至不如Serial收集器(线程交互开销),但随着CPU数目上升,对于其收集效率还是很有提升的。
 
    2.3 Parallel Scavenge收集器
 
        新生代收集器,使用复制算法,其关注点在于控制吞吐量(Throughout,CPU用于运行用户代码与CPU总消耗时间的比值),主要适用于后台运算而不太关注用户交互的场合
 
    2.4 Serial Old收集器
 
        是Serial收集器的老年代版本,单线程,使用标记-清理算法
 
    2.5 Parallel Old收集器
 
        是Parallel Scavege收集器的老年代版本,使用多线程和”标记-整理“算法
 
    2.6 CMS(Concurrent Mark Sweep)收集器
 
        是一种以获取最短停顿时间为目标的收集器,常应用于重视服务响应速度的场景。其基于标记-清除算法。
 
        CMS收集器对CPU资源非常敏感,在并发阶段,虽然不会导致程序停顿,但由于占用了部分CPU资源,导致应用程序变慢,总的吞吐量变低。
        
        CMS无法处理浮动垃圾,可能出现”Concurrent Mode Failure“而导致另外一次Full GC的产生,这是由于在GC过程中,程序仍然运行,会不断产生垃圾所致
 
        CMS可能在收集结束后产生大量碎片,当碎片数量过多时,将会给大对象的分配带来困难
 
    2.7 G1收集器
 
        G1(Garbage First)收集器是最新的GC 收集器,其基于标记 - 整理算法,并且可以非常精确的控制停顿
 
        
    2.8 垃圾收集器总结
 
            没有完美的垃圾收集器,需要根据应用的实际情况进行选择和调优,有时候需要选择不同的收集器,有时需要选择收集器的参数
        
3. 内存分配与回收策略
 
    3.1 对象有优先在Eden区分配,如果没有足够空间,则会发起一次Minor GC -XX:SurvivorRatio=8决定一个新生代Eden与Survivor区比例为8:1
 
        其中新生代GC称为Minor GC,其发生非常频繁,速度也快
 
        其中老年代的GC称为Major GC,比Minor GC慢10倍以上
 
    3.2 大对象直接进入老年代
 
    3.3 长期存活的对象进入老年代(有相应的年龄计数器,活过一次GC则+1)
 
4. 总结
 
    内存回收与垃圾收集器在很多时候都影响系统性能、并发能力的主要因素,虚拟机有大量参数可供调节,只有根据实际需求、实现方式选择最优的收集方式才能获取最优的性能。没有固定收集器-算法的组合,也没有最优的调优方法,需要通过实践去逼近最高性能。
 
           

深入理解Java虚拟机 - 垃圾收集算法与垃圾收集器的更多相关文章

  1. 深入理解java虚拟机(四)垃圾收集算法及HotSpot实现

    垃圾收集算法 一般来说,垃圾收集算法分为四类: 标记-清除算法 最基础的算法便是标记-清除算法(Mark-Sweep).算法分为“标记”和“清除”两个阶段:首先标记处需要收集的对象,在标记完成之后,再 ...

  2. 深入理解java虚拟机(2)------垃圾收集器和内存分配策略

    GC可谓是java相较于C++语言,最大的不同点之一. 1.GC回收什么? 上一篇讲了内存的分布. 其中程序计数器栈,虚拟机栈,本地方法栈 3个区域随着线程而生,随着线程而死.这些栈的内存,可以理解为 ...

  3. 深入理解Java虚拟机 第三章 垃圾收集器 笔记

    1.1   垃圾收集器 垃圾收集器是内存回收的具体实现.以下讨论的收集器是基于JDK1.7Update14之后的HotSpot虚拟机.这个虚拟机包含的所有收集器有: 上图展示了7种作用于不同分代的收集 ...

  4. 《深入理解java虚拟机》读书笔记——垃圾收集与内存分配策略

    可回收判定两种算法 引用计数法(Reference Counting):引用为0时可回收. 可达性分析法(Reachability Analysis): 从GCRoots对象到这个对象不可达. GCR ...

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

    在堆里存放着java世界中几乎所有的对象实例,垃圾收集器在对堆进行回收前需要知道哪些对象还存活,哪些对象已经死去.那怎么样去判断对象是否存活呢? 一.判断对象是否存活算法 1.引用计数法 实现思路:给 ...

  6. 深入理解java虚拟机(五)垃圾收集器

    垃圾收集器 垃圾收集器是垃圾收集算法的具体实现.Java规范对垃圾收集器的实现没有做任何规定,因此不同的虚拟机提供的垃圾收集器可能有很大差异.HotSpot虚拟机1.7版本使用了多种收集器.如下图. ...

  7. 深入理解java虚拟机笔记Chapter3-垃圾收集器

    垃圾收集器 垃圾收集(Garbage Collection,GC),它的任务是解决以下 3 件问题: 哪些内存需要回收? 什么时候回收? 如何回收? 本节补充知识: ① s:Survivor区 新生代 ...

  8. 深入理解java虚拟机(九)类加载器以及双亲委派模型

    虚拟机把类加载阶段中“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到虚拟机外部去实现,以便让程序自己决定如何去获取所需要的类.实现这个动作的代码模块称为“类加载器”. 类与类加载器 任 ...

  9. 《深入理解Java虚拟机》笔记02 -- 垃圾收集算法

    1. 标记 - 清除算法 先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象.它是最基础的收集算法.其他收集算法都是根据其思路,改进其不足之处. 缺点:1) 标记和清除两个阶段的效率都不 ...

  10. 《深入理解Java虚拟机》笔记03 -- 垃圾收集器

    收集器可以大致分为:单线程收集器, 并发收集器和并行收集器. 并行(Parallel):指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态. 并发(Concurrent):指用户线程与垃圾收集 ...

随机推荐

  1. laravel扩展图片处理Intervention Image

    github地址:https://github.com/Intervention/image

  2. H264相关代码

    H.264格式的视频打包成RTP后进行发送,编译环境为VC6++ #include <stdio.h> #include <stdlib.h> #include <str ...

  3. 配置node与express初试

    http://www.nodejs.org/下载对应系统的node版本并安装 用npm包管理器安装需要的包 sudo npm install -g express sudo npm install - ...

  4. 【BZOJ3196】Tyvj 1730 二逼平衡树

    Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的 ...

  5. hadoop 任务执行优化

    任务执行优化 1. 推测式执行: 如果jobtracker 发现有拖后的任务,会再启动一个相同的备份任务,然后哪个先执行完就会去kill掉另一个,因此会在监控页面上经常能看到正常执行完的作业会有被ki ...

  6. [转载]Sublime Text 2 - 性感无比的代码编辑器!程序员必备神器!跨平台支持Win/Mac/Linux

    代码编辑器或者文本编辑器,对于程序员来说,就像剑与战士一样,谁都想拥有一把可以随心驾驭且锋利无比的宝剑,而每一位程序员,同样会去追求最适合自己的强大.灵活的编辑器,相信你和我一样,都不会例外. 我用过 ...

  7. 可编辑的select框的实现(实用版)

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML>  <HEA ...

  8. (转)struts2.0配置文件、常量配置详解

    一.配置: 在struts2中配置常量的方式有三种: 在struts.xml文件中配置 在web.xml文件中配置 在sturts.propreties文件中配置 1.之所以使用struts.prop ...

  9. define中的:#,##,#@

    [define中的:#,##,#@] #define Conn(x,y) x##y #define ToChar(x) #@x #define ToString(x) #x (2)x##y表示什么?表 ...

  10. 使用rsyslog+loganalzey收集日志显示客户端ip

    http://www.ituring.com.cn/article/128536 rsyslog localhost 转发 http://bigsec.net/one/tool/rsyslog.htm ...