苏州做网站公,谷歌seo网站建设,影视自助建站,wordpress首页显示vip标志转载自 JVM内存管理------GC算法精解#xff08;五分钟教你终极算法---分代搜集算法#xff09;引言何为终极算法#xff1f;其实就是现在的JVM采用的算法#xff0c;并非真正的终极。说不定若干年以后#xff0c;还会有新的终极算法#xff0c;而且几乎是一定会有五分钟教你终极算法---分代搜集算法引言何为终极算法其实就是现在的JVM采用的算法并非真正的终极。说不定若干年以后还会有新的终极算法而且几乎是一定会有因为LZ相信高人们的能力。那么分代搜集算法是怎么处理GC的呢对象分类上一章已经说过分代搜集算法是针对对象的不同特性而使用适合的算法这里面并没有实际上的新算法产生。与其说分代搜集算法是第四个算法不如说它是对前三个算法的实际应用。首先我们来探讨一下对象的不同特性接下来LZ和各位来一起给这些对象选择GC算法。内存中的对象按照生命周期的长短大致可以分为三种以下命名均为LZ个人的命名。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流程LZ给出下面图示。图中标注了三个区域中在各个阶段各自内存的情况。相信看着图它的GC流程已经不难理解了。不过有两点LZ需要提一下第一点是使用这样的方式我们只浪费了10%的内存这个是可以接受的因为我们换来了内存的整齐排列与GC速度。第二点是这个策略的前提是每次存活的对象占用的内存不能超过这10%的大小一旦超过多出的对象将无法复制。为了解决上面的意外情况也就是存活对象占用的内存太大时的情况高手们将JAVA堆分成两部分来处理上述三个区域则是第一部分称为新生代或者年轻代。而余下的一部分专门存放老不死对象的则称为年老代。是不是很贴切的名字呢下面我们看看老不死对象的处理方式。老不死对象这一类对象存活率非常高因为它们大多是从新生代转过来的。就像人一样活的年月久了就变成老不死了。通常情况下以下两种情况发生的时候对象会从新生代区域转到年老带区域。1、在新生代里的每一个对象都会有一个年龄当这些对象的年龄到达一定程度时年龄就是熬过的GC次数每次GC如果对象存活下来则年龄加1则会被转到年老代而这个转入年老代的年龄值一般在JVM中是可以设置的。2、在新生代存活对象占用的内存超过10%时则多余的对象会放入年老代。这种时候年老代就是新生代的“备用仓库”。针对老不死对象的特性显然不再适合使用复制算法因为它的存活率太高而且不要忘了如果年老代再使用复制算法它可是没有备用仓库的。因此一般针对老不死对象只能采用标记/整理或者标记/清除算法。方法区的对象回收不灭对象以上两种情况已经解决了GC的大部分问题因为JAVA堆是GC的主要关注对象而以上也已经包含了分代搜集算法的全部内容接下来对于不灭对象的回收已经不属于分代搜集算法的内容。不灭对象存在于方法区在我们常用的hotspot虚拟机JDK默认的JVM中方法区也被亲切的称为永久代又是一个很贴切的名字不是吗其实在很久很久以前是不存在永久代的。当时永久代与年老代都存放在一起里面包含了JAVA类的实例信息以及类信息。但是后来发现对于类信息的卸载几乎很少发生因此便将二者分离开来。幸运的是这样做确实提高了不少性能。于是永久代便被拆分出来了。这一部分区域的GC与年老代采用相似的方法由于都没有“备用仓库”二者都是只能使用标记/清除和标记/整理算法。回收的时机JVM在进行GC时并非每次都对上面三个内存区域一起回收的大部分时候回收的都是指新生代。因此GC按照回收的区域又分了两种类型一种是普通GCminor GC一种是全局GCmajor GC or Full GC它们所针对的区域如下。普通GCminor GC只针对新生代区域的GC。全局GCmajor GC or Full GC针对年老代的GC偶尔伴随对新生代的GC以及对永久代的GC。由于年老代与永久代相对来说GC效果不好而且二者的内存使用增长速度也慢因此一般情况下需要经过好几次普通GC才会触发一次全局GC。结束语GC的相关内容基本上就这些了下一章我们一起探讨一下具体的GC实现都有哪些。