Java为了在每个系统上都能运行所以研发了虚拟机,java的特点就是当他分配了内存机器,他会自动回收,垃圾回收器分十种,但是默认主要是PS PO.
算法最常见的三种是Mark-sweep标记清除,copying拷贝,mark-compact标记压缩.
标记清除容易造成内存碎片化,copy是容易造成内存浪费,标记内存就是效率比copy略低,就在这三个算法基础上构建了十种垃圾回收器.
gc的演化过程其实质上是随着内存的大小不断增长而演进.
对内存的逻辑分区采用1:2的分配方式,小的部分是年轻代,有线程新建后先放入年轻代,回收多次都无法回收掉的放入老年代,一般15-6次,具体是取决于你使用的垃圾回收器,但是这个1:2的比列也不是固定不变的,也能够根据设定的参数不同进行调优.
在新生代主要有两种小的区域,一个是伊甸园区,两个survivor即幸存者区,刚创建的对象首先分配在伊甸园区,在创建的时候会进行一次垃圾回收,将存活对象复制到幸存者区.
等下次扫描时,会将伊甸园区和第一块幸存者区一起扫描,将存活对象存到第二块幸存者区,其余全部回收掉,等下次扫描时,会将第二块幸存者区与伊甸园区一起扫描,将存活后的区域放置到第一块幸存者区中,伊甸园区与幸存者区默认比例为8:1:1.
其实伊甸园区一有对象就会清掉,存活对象实质上是在幸存者区不断复制,等到复制的达到一定次数后复制到老年代.jvm设计时有两个指标,一个是吞吐量一个是响应时间.
cms:对象边处理业务逻辑边四个垃圾回收线程边回收垃圾,这也就是并发垃圾回收.cms一般建议升级为G1.
三色标记算法:操作必须扫描整个老年代不适合大内存,大小必须提前确定,此处的三色指的并不是颜色,本质上指的是对象的三种状态
第一种情况:不一定是没有引用的对象,然后被重新引用,可能是自己已经标记fields都标记完成的对象的引用先指向没有被遍历到的节点对象,,然后自己标记完成但是还没有来得及标记filelds的引用消失.
双标记可以说是黑色对象,单标记为灰色对象,无标记为白色对象
第一种情况最麻烦的情况,双标记指向单指向,此时单指向指向无指向的消失,然后双标记指向无标记的引用诞生了.这种情况下垃圾回收器会把漏标的对象清除.
对于此类情况,CMS方法会选择将黑色对象标记为灰色对象,虽然这个方案有用,但是有bug,因为标记时并发标记,会产生漏标, 所以cms的remark阶段必须从头扫描一遍
G1的解决方案是SATB,在灰色对象指向白色的引用消失的时候,要把这个引用记录到GC的堆栈中,保证灰色对象能被Gc扫描到配合RSet,只用扫描哪些Region引用到这个Region了.
G1在物理上不进行分代,进行分区,每个小的分区可以在逻辑上处于不同类型的区域,在逻辑上分代,每个区域快满的时候清掉,等清空后可以根据各个分区需求来更改空区的逻辑代.
G1的响应时间,200毫秒,比较灵活,分region回收,优先回收花费时间少,垃圾比例高的region(区),在回收时其他region还能够继续使用,无需停止业务.