1.什么是垃圾回收机制

垃圾回收(Garbage Collection)是Java虚拟机(JVM)垃圾回收器提供的
一种用于在空闲时间不定时回收无任何对象引用的对象占据的内存空间的一种机制。

2.什么时候进行垃圾回收

①会在cpu空闲的时候自动进行回收  
②在堆内存存储满了之后  
③主动调用System.gc()后尝试进行回收
补充:System.gc()用于调用垃圾收集器,在调用时,垃圾收集器将运行以回收未使用的内存空间。
它将尝试释放被丢弃对象占用的内存。 然而System.gc()调用附带一个免责声明,无法保证对垃圾收集器的调用。
 所以System.gc()并不能说是完美主动进了垃圾回收。

3.如何判断对象已死(或能够被回收)

①引用计数法
简单的来说就是判断对象的引用数量。实现方式:给对象共添加一个引用计数器,
每当有引用对他进行引用时,计数器的值就加1,当引用失效,也就是不在执行此对象,
它的计数器的值随之减1,若某一个对象的计数器的值为0,那么表示这个对象没有被其他对象引用,
也就是意味着是一个失效的垃圾对象,就会被gc进行回收。 但是这种简单的算法在当前的jvm中并没有采用,
原因是他并不能解决对象之间循环引用的问题。 假设有A和B两个对象之间互相引用,
也就是说A对象中的一个属性是B,B中的一个属性时A,这种情况下由于他们的相互引用,从而垃圾回收机制无法识别。
②可达性分析算法(根搜索算法)
通过一系列名为GC Roots的对象作为起点,从这些节点往下搜索,搜索走过的路径称为引用链。
当一个对象到GC Roots没有任何引用链相连时(意味着GC Roots到这个对象不可达),
证明该对象是不可用的,则应该被回收
在这里插入图片描述

4.垃圾回收算法的种类

按照方法分类:

①标记-清理算法

分为两个步骤:第一就是标记,也就是标记所有的需要回收的对象;第二就是清理,标记完成后进行统一的回收带有标记的对象占据的内存空间。缺点是效率问题,还有一个致命的缺点就是空间问题,标记清除之后会产生大量不连续的内存碎片,当程序在运行过程中需要分配较大对象时,无法找到足够的连续内存而造成内存空间浪费。
在这里插入图片描述

②复制算法

复制算法是将内存容量划分为大小相等的两块,每次只使用其中的一块。当一块内存用完之后,就将还存活的对象复制到另一块上面,然后再把已使用的内存空间一次性清理。这样使得每次都对其中的一块进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况,只是这种算法的代价就是将内存缩小为原来的一半了。
在这里插入图片描述

③标记-整理算法

标记整理算法与标记清除算法很相似,但显著的区别是:标记清除算法仅对不存活的对象进行处理,剩余存活对象不做任何处理,这就造成了内存碎片的问题;而标记整理算法不仅对不存活的对象进行清除,还对存活的对象进行重新整理,因此不会产生内存不连续的现象。
在这里插入图片描述

按照回收策略分类

分代收集算法

分代收集算法是一种比较智能的算法,也是现在jvm使用最多的一种算法,它本身其实不是一个新的算法,而是他会在具体的场景自动选择以上三种算法进行垃圾对象回收。在jdk1.7之前,对JVM分为三个区域:新生代、老年代、永久代

①新生代

新生代的目标就是尽可能快速的收集掉那些生命周期较短的对象,一般情况下新生成的或者朝生夕亡的对象一般都是首先存放在新生代里面。
在这里插入图片描述
新生代将内存按照8:1:1分为一个Eden和so,s1三个区域;大部分对象都在Eden区域生成,在垃圾回收时,先将Eden存活的对象复制到s0区,然后清除Eden区,当这个s0区满了,则将Eden区和s0区的存活对象复制到s1,然后将Eden和s0区清空,此时s0是空的,然后交换s0和s1的角色(即下次回收会扫描eden和s1区),即保持s1为空,如此往复;特别地,当s1不足以存放Eden和s0存放的对象时,则将对象直接放到老年代)

适用回收算法:复制算法

在新生代中,每次垃圾回收都有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成垃圾收集

②老年代

老年代一般存放的是一些生命周期较长的对象,比如在新生代中经历来了n次垃圾回收后仍然存活的对象都进入了老年代。

适用回收算法:标记整理或标记清除

在老年代中因为对象存活率较高,没有额外的空间对它分配担保,就必须使用标记清除或标记整理

③永久代

永久代主要存放静态文件,如java类,方法等,永久代对垃圾回收没有显著影响。
在这里插入图片描述
转载于

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐