二 JVM.垃圾回收算法/策略内存分配

JVM(二).垃圾回收算法/策略&内存分配 1.概述
内存释放动态化:那些内存需要回收;什么时候回收;如何回收;
2.回收那些对象
垃圾回收的是不需要被使用的对象,就是可以被回收的,如何确定?
2.1 引用计数
在对象中,添加引用计数,一个地方引用+1,引用失效-1,如何时刻计数器是0 的时候就是可以回收对象了;
明显的缺点:循环引用;(a 引用b ,b 引用a,但是a,b 都没有其他引用了,这个时候是应该被回收了)
2.2 可达性分析
主流语言都在使用的,通过一系列称为 GC Roots 的节点作为其实节点集,来搜索引用链Chain,如果一个对象没有连接到引用链,或者叫这个对象不可达,这个对象可以被回收了;
在Java体系里面 固定的 GC Roots 有以下几种
2.3 引用的级别
级别的作用就是:当内存够时,我们可以都保留,内存比较紧张的时候,就可以根据引用的级别回收固定级别的这些对象;
2.4 回收/继续存活
被可达性分析算法判定后为不可达对象后,也不是马上必须去回收,至少会有两次标记的过程:
引用链不可达是否需要执行() ,如果没有重写这个方法或者这个方法已经被调用(一个对象只会调用一次),就不会再执行这个方法;如果要执行,放入F-Queue对列,该虚拟机低优先级线程执行对列对象的 (),如果在方法里面重写建立连接,就可以避免回收,但是也有可能等不到执行就会被GC了
不建议使用!!!!
2.5 回收方法区
虚拟机规范中可以不要求实现方法区的内存回收,也有不能回收方法区的垃圾回收器(JDK11 的ZGC),回收性价比低,回收条件复杂;
回收具体有两大类:废物的常量和不在使用的类型;
第二个实现比较复杂 需要做一下判断 :
参数控制: 是否方法区 GC - ,加载和卸载信息 -:class,-XX:+;-XX:+
在使用反射,动态代理,CGLib一些字节码框架,动态生成JSP,OGSi 自定义类加载器 需要虚拟机具备类型卸载功能,来保证方法区可用;
3.垃圾回收算法 3.1 分代收集理论
1.弱分代假说:大部分对象是短暂的
2.强分代假说:多次垃圾回收后还存在就越难以消亡;
垃圾回收器回收对象的时候根据对象的年龄划分到不同的区域;也就是将上面说的短暂对象放在一起和多次GC还存在的对象放在一起;提示回收效率;针对不同的区域,又有好几个回收类型 Minor GC , Major GC, Full GC ,在进而对不同类型的 GC 有了不同的算法 标记复制 标记清楚 标记整理等回收算法;
3.跨代引用假说:占比较少,垃圾回收的年代不是孤立的
年轻代的回收需要判断是否被老年代引用,需要把老年代加入GC Roots 但是开销巨大 ,而且就算是扫描了 年轻代的引用也会由于老年代的引用而进入老年代,为每一个对象存储跨代引用也比较浪费;所以在新生代创建一个Set 数据结构用于划分老年代内存块,记录年轻代关联老年代的区域,在 Minor GC 的时候,把块内对象加入GC Roots 就可以了;
整堆收集 Full GC : 整个Java堆和方法区的内存回收; 3.2 标记-清除算法
Mark-Sweep 算法:两个阶段,标记要回收的对象,统一回收标记的算法;也可以反着来,标记或者的对象,清除没有被标记的对象;
比较基础的垃圾回收算法,后面的回收算法大部分是以这个为基础;该算法的主要缺点有两个:执行效率不稳定,两个阶段的执行效率随着对象数量变多而降低;第二个就是执行后内存空间碎片化的问题,无法获取连续的内存空间;
3.3 标记-复制算法
内存等量划分两块,每次只用一块,一块使用完了,或者的对象复制到另一块上面去,已使用的那块全部清除;