对象分类
  上次已经说过,分代收集算法是针对对象的不同特性,而使用合适的算法,这里面并没有实际上的新算法产生。与其说分代收集算法是第四个算法,不如说它是对前三个算法的实际应用。 
  首先我们来探讨一下对象的不同特性,接下来博主和各位来一起给这些对象选择GC算法。 
  内存中的对象按照生命周期的长短大致可以分为三种,以下命名均为博主个人的命名。 
  1、夭折对象:朝生夕灭的对象,通俗点讲就是活不了多久就得死的对象。 
  例子:某一个方法的局域变量、循环内的临时变量等等。 
  2、老不死对象:这类对象一般活的比较久,岁数很大还不死,但归根结底,老不死对象也几乎早晚要死的,但也只是几乎而已。 
  例子:缓存对象、数据库连接对象、单例对象(单例模式)等等。 
  3、不灭对象:此类对象一般一旦出生就几乎不死了,它们几乎会一直永生不灭,记得,只是几乎不灭而已。 
  例子:String池中的对象(享元模式)、加载过的类信息等等。
对象对应的内存区域
  还记得前面介绍内存管理时,JVM对内存的划分吗? 
  我们将上面三种对象对应到内存区域当中,就是夭折对象和老不死对象都在JAVA堆,而不灭对象在方法区。 
  之前的文章中我们就已经说过,对于JAVA堆,JVM规范要求必须实现GC,因而对于夭折对象和老不死对象来说,死几乎是必然的结局,但也只是几乎,还是难免会有一些对象会一直存活到应用结束。然而JVM规范对方法区的GC并不做要求,所以假设一个JVM实现没有对方法区实现GC,那么不灭对象就是真的不灭对象了。 
  由于不灭对象的生命周期过长,因此分代收集算法就是针对的JAVA堆而设计的,也就是针对夭折对象和老不死对象。
JAVA堆的对象回收(夭折对象和老不死对象)
  有了以上分析,我们来看看分代收集算法如何处理JAVA堆的内存回收的,也就是夭折对象与老不死对象的回收。 
  夭折对象:这类对象朝生夕灭,存活时间短,还记得复制算法的使用要求吗?那就是对象存活率不能太高,因此夭折对象是最适合使用复制算法的。 
  疑问:50%内存的浪费怎么办? 
  答疑:因为夭折对象一般存活率较低,因此可以不使用50%的内存作为空闲,一般的,使用两块10%的内存作为空闲和活动区间,而另外80%的内存,则是用来给新建对象分配内存的。一旦发生GC,将10%的活动区间与另外80%中存活的对象转移到10%的空闲区间,接下来,将之前90%的内存全部释放,以此类推。 
  为了让各位更加清楚的看出来这个GC流程,博主给出下面图示。 

图中标注了三个区域中在各个阶段,各自内存的情况。相信看着图,它的GC流程已经不难理解了。
  不过有两点博主需要提一下: 
  第一点是:使用这样的方式,我们只浪费了10%的内存,这个是可以接受的,因为我们换来了内存的整齐排列与GC速度。 
  第二点是:这个策略的前提是,每次存活的对象占用的内存不能超过这10%的大小,一旦超过,多出的对象将无法复制。
  为了解决上面的意外情况,也就是存活对象占用的内存太大时的情况,高手们将JAVA堆分成两部分来处理,上述三个区域则是第一部分,称为新生代或者年轻代。而余下的一部分,专门存放老不死对象的则称为年老代。
  是不是很贴切的名字呢?下面我们看看老不死对象的处理方式。 
  老不死对象:这一类对象存活率非常高,因为它们大多是从新生代转过来的。就像人一样,活的年月久了,就变成老不死了。
  通常情况下,以下两种情况发生的时候,对象会从新生代区域转到年老带区域。 
  1、在新生代里的每一个对象,都会有一个年龄,当这些对象的年龄到达一定程度时(年龄就是熬过的GC次数,每次GC如果对象存活下来,则年龄加1),则会被转到年老代,而这个转入年老代的年龄值,一般在JVM中是可以设置的。 
  2、在新生代存活对象占用的内存超过10%时,则多余的对象会放入年老代。这种时候,年老代就是新生代的“备用仓库”。
  针对老不死对象的特性,显然不再适合使用复制算法,因为它的存活率太高,而且不要忘了,如果年老代再使用复制算法,它可是没有备用仓库的。因此一般针对老不死对象只能采用标记/整理或者标记/清除算法。
方法区的对象回收(不灭对象)
  以上两种情况已经解决了GC的大部分问题,因为JAVA堆是GC的主要关注对象,而以上也已经包含了分代搜集算法的全部内容,接下来对于不灭对象的回收,已经不属于分代收集算法的内容。 
  不灭对象存在于方法区,在我们常用的hotspot虚拟机(JDK默认的JVM)中,方法区也被亲切的称为永久代,又是一个很贴切的名字不是吗? 
  其实在很久很久以前,是不存在永久代的。当时永久代与年老代都存放在一起,里面包含了JAVA类的实例信息以及类信息。但是后来发现,对于类信息的卸载几乎很少发生,因此便将二者分离开来。幸运的是,这样做确实提高了不少性能。于是永久代便被拆分出来了。 
  这一部分区域的GC与年老代采用相似的方法,由于都没有“备用仓库”,二者都是只能使用标记/清除和标记/整理算法。
回收的时机
  JVM在进行GC时,并非每次都对上面三个内存区域一起回收的,大部分时候回收的都是指新生代。因此GC按照回收的区域又分了两种类型,一种是普通GC(minor GC),一种是全局GC(major GC or Full GC),它们所针对的区域如下。 
  普通GC(minor GC):只针对新生代区域的GC。 
  全局GC(major GC or Full GC):针对年老代的GC,偶尔伴随对新生代的GC以及对永久代的GC。 
  由于年老代与永久代相对来说GC效果不好,而且二者的内存使用增长速度也慢,因此一般情况下,需要经过好几次普通GC,才会触发一次全局GC。
 

JVM-GC算法(三)-分代收集算法的更多相关文章

  1. JVM之GC算法、垃圾收集算法——标记-清除算法、复制算法、标记-整理算法、分代收集算法

    标记-清除算法 此垃圾收集算法分为“标记”和“清除”两个阶段: 首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记对象,它的标记过程前面已经说过——如何判断对象是否存活/死去 死去的对象就会 ...

  2. JVM垃圾收集算法——分代收集算法

    分代收集算法(Generational Collection): 当前商业虚拟机的垃圾收集都采用"分代收集算法". 这种算法并没有什么新的思想,只是根据对象存活周期的不同将内存划分 ...

  3. jvm 分代回收算法通俗理解

    jvm区域总体分两类,heap区和非heap区.heap区又分:Eden Space(伊甸园).Survivor Space(幸存者区).Tenured Gen(老年代-养老区). 非heap区又分: ...

  4. JVM的stack和heap,JVM内存模型,垃圾回收策略,分代收集,增量收集

    (转自:http://my.oschina.net/u/436879/blog/85478) 在JVM中,内存分为两个部分,Stack(栈)和Heap(堆),这里,我们从JVM的内存管理原理的角度来认 ...

  5. JVM内存管理------GC算法精解(五分钟教你终极算法---分代搜集算法)

    引言 何为终极算法? 其实就是现在的JVM采用的算法,并非真正的终极.说不定若干年以后,还会有新的终极算法,而且几乎是一定会有,因为LZ相信高人们的能力. 那么分代搜集算法是怎么处理GC的呢? 对象分 ...

  6. JVM内存管理之GC算法精解(五分钟教你终极算法---分代搜集算法)

    引言 何为终极算法? 其实就是现在的JVM采用的算法,并非真正的终极.说不定若干年以后,还会有新的终极算法,而且几乎是一定会有,因为LZ相信高人们的能力. 那么分代搜集算法是怎么处理GC的呢? 对象分 ...

  7. GC算法精解(五分钟教你终极算法---分代搜集算法)

    GC算法精解(五分钟教你终极算法---分代搜集算法) 引言 何为终极算法? 其实就是现在的JVM采用的算法,并非真正的终极.说不定若干年以后,还会有新的终极算法,而且几乎是一定会有,因为LZ相信高人们 ...

  8. JVM内存管理--分代搜集算法

    对象分类 分代搜集算法是针对对象的不同特性,而使用适合的算法,这里面并没有实际上的新算法产生.与其说分代搜集算法是第四个算法,不如说它是对前三个算法的实际应用. 首先我们来探讨一下对象的不同特性,接下 ...

  9. JVM系列-分代收集垃圾回收

    Java自动垃圾回收(Automatic Garbage Collection)是自动回收堆上不再使用的内存,new的对象在程序中没有引用指向它,就会被回收.回收的实现很多,有Reference Co ...

随机推荐

  1. JS基础_if语句

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  2. wpf之二进制资源

    一.当需要添加图片.音频.视屏的资源到wpf项目里是,可以直接把文件添加到项目里 右击add->existing item. 1.如果想将外部文件编异常目标成为二进制资源,在文件的属性窗口 Bu ...

  3. mqtt协议实现 java服务端推送功能(一)安装

    最近有个新需求,需要通过java服务端把信息推送到mqtt服务器上,安卓和ios端从mqtt服务器上获取信息实现推送. 1. 本地需要安装Mosquitto服务器  http://mosquitto. ...

  4. js之语句(表达式语句,复合语句,声明语句)

    语句就是JavaScript整句或命令,以分号结束,用来执行以使某件事发生.下面将介绍三种语句:表达式语句,复合语句,声明语句. 一.表达式语句 表达式语句是javascript中最简单的语句 < ...

  5. vue 超大 table

    https://github.com/ColdDay/vue-fast-table https://coldday.github.io/vue-fast-table/dist/index.html h ...

  6. linux递归查找目录下所有文件夹以及文件

    相对于ls或者ll,可能find在这个时候更加给力 先看我的目录结构 tree命令是查看目录的结构,而且最后会列出所有的directory的数目以及文件夹的数目...好像我们接下来要做的就没有必要了, ...

  7. Redis+Sentinel安装与配置

    在这里我们搭建的是一个1主3从的redis+3个哨兵集群的环境,由于是在一台物理机上,所有我们用端口区分. 物理机IP:192.168.0.12 主节点master端口:6301 从节点slave1端 ...

  8. 【异常】Caused by: org.apache.phoenix.coprocessor.HashJoinCacheNotFoundException:

    1 详细异常 Caused by: org.apache.phoenix.coprocessor.HashJoinCacheNotFoundException: ERROR 900 (HJ01): H ...

  9. LVS (Linux虚拟服务器)-不同的负载均衡方法

    随着Internet用户的增长,基于Web的公司处理的通信量急剧增加.有各种解决方案来应对这种不断增长的流量. 一种解决方案是垂直扩展服务器(即:简单地向服务器添加更多的CPU和内存资源.)当然在一定 ...

  10. “联邦对抗技术大赛”9月开战 微众银行呼唤开发者共同“AI创新”

    “联邦对抗技术大赛”9月开战  微众银行呼唤开发者共同“AI创新”   从<第五元素>中的智能系统到<超体>中的信息操控,在科幻电影中人工智能已经发展到了极致.而在现实中,目前 ...