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. syntaxhighlighter语法高亮

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

  2. 各种语言简单的输出Hello World

    PHP echo 'Hello World'; Java System.out.println("Hello World"); Shell_(BashShell) echo Hel ...

  3. python开源项目及示例代码

    本页面是俺收集的各种 Python 资源,不定期更新. 下面列出的各种 Python 库/模块/工具,如果名称带超链接,说明是第三方的:否则是 Python 语言内置的. 1 算法 1.1 字符串处理 ...

  4. 以a为变量名,给出下列描述的定义

    a)一个整型数(An integer) b) 一个指向整型数的指针(A pointer to an integer) c) 一个指向指针的的指针,它指向的指针是指向一个整型数(A pointer to ...

  5. sql之表连接 筛选条件放在 连接外和放在连接里的区别

    使用一个简单的例子,说明他们之间的区别 使用的表:[Sales.Orders]订单表和[Sales.Customers]客户表,和上一篇博客的表相同 业务要求:查询出 : 所有的用户 在 2012-1 ...

  6. windows环境下装node.js,npm,express

    windows下安装跟mac环境安装(戳我戳我戳我)大同小异. 1. 下载node.js for Mac 地址: http://nodejs.org/download/ 注意看自己系统是32位还是64 ...

  7. 小啃机器学习(1)-----ID3和C4.5决策树

    第一部分:简介 ID3和C4.5算法都是被Quinlan提出的,用于分类模型,也被叫做决策树.我们给一组数据,每一行数据都含有相同的结构,包含了一系列的attribute/value对. 其中一个属性 ...

  8. HTTP verb的安全性和幂等性

    Http协议规定了不同方法的安全特性和幂等特性,作为服务提供者的服务器必需为客户端提供这些特性. 安全性,仅指该方法的多次调用不会产生副作用,不涉及传统意义上的“安全”,这里的副作用是指资源状态.即, ...

  9. 1062: [NOI2008]糖果雨 - BZOJ

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1062 神题一个,直接讲思路了(全都是看别人的) 首先我们把一个云用一个平面上的点( ...

  10. 【高斯消元】BZOJ 1770: [Usaco2009 Nov]lights 燈

    Description 貝希和她的閨密們在她們的牛棚中玩遊戲.但是天不從人願,突然,牛棚的電源跳閘了,所有的燈都被關閉了.貝希是一個很膽小的女生,在伸手不見拇指的無盡的黑暗中,她感到驚恐,痛苦與絕望. ...