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

来源:互联网 发布:数据库远程连接工具 编辑:程序博客网 时间:2024/05/16 01:19
三个问题
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%的空间,大大节约了空间。
缺点:还是不能完整利用所有空间,而且对存活率比较高时要进行很多次操作,而且效率会很低。
但是就新生代这种存活率很低的情况下还是很合适的,而且使用这种算法的前提条件是还有块额外的空间提供担保,对于新生代来说就是老年代担保。

③标记-整理算法
这个算法就是在①的基础上,在清除之后,对内存进行整理,让存活的对象向一端移动。
老年代没有担保的空间,所有而且老年代对象存活率较高,适合这种算法进行内存回收。
0 0
原创粉丝点击