JAVA虚拟机--垃圾回收算法

    xiaoxiao2021-03-25  112

    三个问题 1.哪些内存需要回收 2.什么时候回收 3.如何回收 1.主要的回收对象是JAVA堆里面的对象,这里的空间占了大多数空间。 这里面哪些对象要回收呢?主要是一些死掉的对象,也就是没有被引用的对象。 判断这些对象有两种算法: ①引用计数算法:每个对象加一个引用计数器,每次引用一次对象,计数器加一;引用失效,计数器减一。    缺点:无法解决循环引用的问题。 ②可达性算法分析:通过一系列的GC ROOTS对象最为起始点,往下找对象,如果一个对象的引用链没有ROOTS对象,说明这个对象以失效 GC ROOTS对象可以是:虚拟机栈引用的对象、方法区中类静态属性引用的对象,方法区中常量引用的对象,本地方法栈中的JNI 2.什么时候回收? 首先要说说目前大多数商用的虚拟机都采用分代垃圾收集。 也就是把内存分为两代,新生代和老年代。 新生代内存又分为两种类型Edem区和Survivor区。Survicor区又分为Survivor From区 和Survivor To区。 其中Edem区占新生代80%的空间,两个Survivor区各占10%的空间(空间分配的原因下面会说) 上面是科普,那么什么时候开始回收内存呢? ①JAVA虚拟机分配新的对象一般分配到新生代的Edem区和Survivor From区, 当这两个区的内存放不下的时候,这时系统开始GC(垃圾回收),并且把GC后存活下来的对象转移到Survivor区 ②循环往复1的过程之后,直到Survivor To区放不下第一步GC存活的对象,这些对象就会都移到老年代 3.如何回收? 根据上面可以知道有两步需要回收内存。 1.新生代Edem+Survivor区-->Survivor To区:这里常用到的是①复制算法 2新生代Survivor To 区-->老生代区 这里常用的是③标记-整理算法 接下来具体讲一下上述算法 首先讲一下最基础的算法 ①标记-清除算法:就像名字一样,分为两步,标记和清除。标记就是用1里的那两种算法①引用计数算法②可达性算法分析 对无效的对象进行标记,清除就直接回收内存,不做其他处理。 缺点:很明显,首先效率不高,两步的效率都并不高,其次空间问题,清除之后会产生大量不连续的空间 为了解决上述的问题,下面的复制算法就出来了 ②复制算法:复制算法的原始是这样的,将内存分为两大块,当其中一块内存装满之后,进行一次GC, 将还存活的对象转移到另一块内存中,但是这样相当于每次只用一半的内存,损耗就比较大。于是在实际运用中, 也就是新生代的回收,是将其中一块分配90%的空间(Edem+Survivor区 ),另一块分配10%的空间(Survivor To 区 ), 这样相当于,利用了90%的空间,大大节约了空间。 缺点:还是不能完整利用所有空间,而且对存活率比较高时要进行很多次操作,而且效率会很低。 但是就新生代这种存活率很低的情况下还是很合适的,而且使用这种算法的前提条件是还有块额外的空间提供担保,对于新生代来说就是老年代担保。 ③标记-整理算法 这个算法就是在①的基础上,在清除之后,对内存进行整理,让存活的对象向一端移动。 老年代没有担保的空间,所有而且老年代对象存活率较高,适合这种算法进行内存回收。
    转载请注明原文地址: https://ju.6miu.com/read-5433.html

    最新回复(0)